第四周python总结

110 阅读7分钟

*与**在实参中的作用

形参实参
*号会把溢出来的位置组成元组然后赋值给其后的形参名*号会把值打散 字符串会变成单个字符
**号会把溢出来的关键字实参存成字典,然后赋值其后的形参名**只能跟字典 只能将字典的key进行打散

名称空间

就是用来存储变量名和数据值之间绑定关系的地方

  • 内置名称空间:python自带的空间 当解释器运行就会创建的,当解释器关闭就会销毁。
  • 局部名称空间:函数体代码运行就会创建的文件就会存入这个空间,当函数体代码关闭空间也就关闭了。
  • 全局名称空间:py文件运行产生的文件就会存入这个空间,当py文件运行结束也就结束了。普通代码的变量名,分支结构的变量名,循环结构的变量名,定义函数的函数名,定义类的类名。

名字查找顺序

查找名字之前一定要看清自己在那个空间名称,名字的查找顺序不能够颠倒只能够局部>>>全局>>>内置;

global和nonlocal

money=999
def money():
    global=money
    money=1000
    print()
这里的global修改的是全局的money  最终的到的结果是1000

def func1():
   x=1
   了=【1,2】
   def func2()
   nonloca x
   x=999
   l1.append
 func1()
 print(x)
 print(l1)
 func()
 这里的nonloca修改的是局部的x  在内存局部名称空间修改外层局部名称空间中的不可变类型

函数名多种使用方法

  • 函数名可以被用来多次赋值(函数名与便令明使用一直)
  • 函数名还可以当作函数名的实参
  • 函数名还可以当成函数的返回值
  • 函数名还可以当成容器类型里面的数据值

闭包函数

* 定义在函数内部的函数
* 内部函数是用了外部函数才能称之为闭包函数
def func(username):
   username='jason'
   def index():
       print(username)
     return index
res=func()
print(res)
res()

闭包函数的使用

 * 通过形参的方式进行传值
 def funcxxx
    print(xxx) 
 * 通过闭包函数进行传参
 def index(username): 
 username='yqb' 
    def func():
     print(username):
 return func
 res=index('yqb') res()

装饰器简介

* 在不改变装饰对象原来的调用方式和内部代码的情况下给被装饰对象添加新的功能
    def func():
       print(123)
    func() 
 * 装饰器的原则是对修改封闭  对扩展开放
 * time.time()实际是在统计代码运行的时间 
# 装饰器前期推导
def index()
  time.sleep(3)
  print('from index')
  start_time=time.time() #在调用index函数之前获取一下时间戳
  index()  # 调用index函数
  end_time=time.time()
  print(end_time-start_time)
  在这里的index如果有多个那就需要重复编写代码  那么我们就要将其封装成函数

 def get_time():
    start_time = time.time()  # 在调用index函数之前获取一下时间戳
    index()  # 调用index函数
     end_time = time.time()
     print('函数的执行时间是:',end_time - start_time)
如果有多个不同的函数需要统计时间那这个解决措施也是不行的  需要给函数体动态传参形参
def home():
time.sleep(5)
print('from home')

def get_time(xxx):
    start_time = time.time()  # 在调用index函数之前获取一下时间戳
    xxx(*args,**kwargs)  # 调用index函数
    end_time = time.time()
    print('函数的执行时间是:',end_time - start_time)
 get_time(index)
 get_time(home)
 不同的形参个数的函数无法共同进行统计  我们使用了*args **kwargs

def func1(a):
    time.sleep(1)
    print('from func1')
get_time(func1)
这我们改变了原来的调用方式是不可取的   我们需要进行装饰器推到流程

装饰器的固定模板

from functools import wraps
def outer(func_name):
    @wraps(func_name)  # 仅仅是为了让装饰器不容易被别人发现 做到真正的以假乱真
    def inner(*args, **kwargs):
        print('执行被装饰对象之前可以做的额外操作')
        res = func_name(*args, **kwargs)
        print('执行被装饰对象之后可以做的额外操作')
        return res
    return inner

语法糖内部原理:

1.使用的时候最好紧跟在被装饰对象的上方\
2.语法糖会自动将下面紧挨着的函数名传给@后面的函数调用 import time
@outer  #  home = outer(真正的函数名home)
def home():
    '''我是home函数 我要热死了!!!'''
    time.sleep(1)
    print('from home')
    return 'home返回值'

 help(home)
print(home)
home()

 def index():
     '我是index函数 '
     pass

 help(index)

多层装饰器

def outter1(func1):
    print('加载了outter1')
    def wrapper1(*args, **kwargs):
        print('执行了wrapper1')
        res1 = func1(*args, **kwargs)
        return res1
    return wrapper1

def outter2(func2):
    print('加载了outter2')
    def wrapper2(*args, **kwargs):
        print('执行了wrapper2')
        res2 = func2(*args, **kwargs)
        return res2
    return wrapper2

def outter3(func3):
    print('加载了outter3')
    def wrapper3(*args, **kwargs):
        print('执行了wrapper3')
        res3 = func3(*args, **kwargs)
        return res3
    return wrapper3


@outter1
@outter2
@outter3
def index():
    print('from index')
多层装饰器先看有多少个语法糖  由下而上的看  遇到最后一个才会使用相同的变量名传给装饰器函数使用  

有参装饰器

def login_auth(func_name):
        def inner(*args, **kwargs):
            username = input('username>>>:').strip()
            password = input('password>>>:').strip()
            if username == 'jason' and password == '123':
                res = func_name(*args, **kwargs)
                return res
            else:
                print('用户权限不够 无法调用函数')
        return inner
有参函数的目的就是给装饰器传递额外的参数,装饰器最多就三层嵌套,三层嵌套的结构使用率不高

递归函数

* 递归函数也就是间接的调用了自己
 递归调用:直接调用
 def index():
     print('from index')
     index()
 index()
 递归调用:间接调用
 def index():
     print('from index')
     func()
 def func():
     print('from func')
     index()
 func() 

在python中函数量最大调用量是1000 但是实际都会在996 ,997。

  • 递归函数真正的应用场景 递推:一层层的往下去寻找答案

回溯:根据已知条件推导最终的条件

每次调用的时候都必须比上一次要简单 而且在结束的时候要有一个明确的结束条件。

算法之二分法

  • 算法就是解决问题的方法 也是最简单的算法
  • 缺陷:在二分法中数据必须是有序的 而且查找的效率是最低的

三元表达式

* 三元表达式:值 if 条件 else2
如果if后面的值成立则使用if前面的值

如果if后面的条件不成立 则使用else后面的值
username = input('username>>>:').strip()
 if username == 'yqb':print('欢迎')
 else:print('滚蛋')   
print('欢迎') if username == 'yqb' else print('滚蛋')

各种生成式

通过列表生成式可以快速的生成一个新的列表而且代码更加的简洁
name_list = ['jason', 'kevin', 'oscar', 'jerry', 'tony']
 给上述列表中所有的数据值加上_NB的后缀
new_list=[]  # 定义一个新的列表
for name in name_list:  # 循环列表中的数据
    new_name=name+'_NB'   #在原有的列表数据后加上_NB
    new_list.append(new_name)  # 将添加好的数据放进新的列表中
    print(new_list)#  打印新的列表

new_list=[name+'_NB'for name in name_list]  # 先让for循环然后将数据值交给for循环前面处理
print(new_list)# 


new_list=[name+'_NB'for name in name_list if name!='jason']
print(new_list)#  列表生成式中只能出现for和if


  字典生成式
new_dict={i:'jason'for i in range(10) if i ==6 }
print(new_dict)  #  最终打印出来的是{6:’jason‘}


# 集合生成式
new_set={i for i in range(10)if i==6}
print(new_set)

 针对元组是没有生成式的


# 匿名函数
 匿名函数就是没有函数名的函数
 结构由  lambda 形参:返回值
(lambda x:x+1)(123)   #x=参数  x+1=返回值  直接调用
res =lambda x:x+1   #  直接命名调用
print(res(123))
这里的匿名函数是需要配合其他的函数一起使用  其目的是为了减少代码

重要匿名集合内置函数使用

  • max(求最大值)

当需要在一个数据中求取最大的数值时直接使用

  • min(求最小值)

当需要在一个数据中求取最小的数据值直接使用

  • map(自增)

当一个数据值需要将每个数据值都增加到某个数时可以使用

  • filten(移除)

在一个数据中需要将某个数据值移除可以使用这个

  • reduce(求和)

需要求取一个数据总和的时候使用

  • zip(合并)

将两个以上的数据对应好位置组成元组 然后新的元组