函数-----函数进阶(闭包、无参装饰器、有参装饰器、迭代器、生成器)
一、名称空间
顾名思义就是存放名字的地方;举例:若变量X=1,1存放在内存中,是存放名字X与1绑定关系的地方。
名称空间有三种:
1.locals:函数内的名称空间,包括局部变量和形参
2.globals:全局变量,函数定义锁在模块的名字空间
3.builtins: 内置模块的名字空间
二、作用于的查找顺序
LEGB顺序
locals--->enclosing(外部嵌套函数的名称空间)--->globals--->builtins
三、闭包
即函数定义和函数表达式位于另一个函数的函数体内(嵌套函数)。而且,这些函数可以访问他们所在的外部函数中声明的所有局部变量、参数。当其中一个这样的内部函数在包含他们的外部函数之外被调用时,就会形成闭包。
闭包的意义:返回的函数对象,不仅仅是一个函数对象,在函数对象外还包含了一层作用于,这使得,该函数无论在何处调用,优先使用自己外层包裹的作用域。
def func(): n = 10 def func2(): print('func2:',n) return func2 f = func() print(f) f() >>>><function func.<locals>.func2 at 0x000001F9C4B1B9D8> >>>>func2: 10
为函数传参的两种方式:
方式一:直接把函数需要的参数定义成形参
方式二:利用闭包函数传参
def func(): x = 4 def func2(): print(x) return func2 res = func() print(res) res()
四、装饰器
定义:定义一个工具,该工具是用来装饰其他函数的,来增加额外功能的。
为什么要用装饰器:在不修改被装饰器源代码对象以及调用方式的前提下,为被装饰对象添加新功能。
开放封闭原则:对拓展功能是开放的;对修改源代码是封闭的。
import time def index(x,y,z): time.sleep(3) print('index%s %s %s' %(x,y,z)) return 666 # print(index)-------<function index at 0x000001A2AD783E18> def outter(func1): # func = index的内存地址 def wrapper(*args,**kwargs): start = time.time() res = func1(*args,**kwargs) # index的内存地址 stop = time.time() print(stop - start) return res return wrapper index = outter(index) # outter的内存地址 # print(index)-----<function outter.<locals>.wrapper at 0x000001A2AF67BA60> res = index(3,5,6,) print('返回值----',res) # 结果 # >>> index3 5 6 # >>> 3.000042200088501 # >>> 返回值---- 666
语法糖:当需要同一个装饰器装饰不同的函数的时候,可以把装饰器写在最上面,在函数的上面单独一行@装饰器名字
import time def outter(func1): # func = index的内存地址 def wrapper(*args,**kwargs): start = time.time() res = func1(*args,**kwargs) # index的内存地址 stop = time.time() print(stop - start) return res return wrapper @outter def index(x,y,z): time.sleep(3) print('index%s %s %s' %(x,y,z)) return 666
装饰器模板
def outter(func): def wrapper(*args,**kwargs): # 1.调用原函数 # 2.增加新功能 res = func(*args,**kwargs) return res return wrapper
加了装饰器之后如果需要保持和原函数的属性一直,操作如下:应用wraps
import time from functools import wraps # 导入wraps功能 def timmer(func): '''计时器''' @wraps(func) # 自动将原函数func的属性赋值给wrapper def wrapper(*args,**kwargs): strat = time.time() res = func(*args,**kwargs) stop = time.time() print(stop - strat) return res # 手动将原函数的属性赋值给wrapper # 1.函数wrapper.__name__ = 原函数.__name__ # 2.函数wrapper.__doc__ = 原函数.__doc__ # 1.wrapper.__name__ = func.__name__ # 2.wrapper.__doc__ = func.__doc__ return wrapper @timmer def login_in(x): '''登入验证''' time.sleep(2) print('登入成功!',x) login_in(222) print(login_in.__name__) print(login_in.__doc__) # >>>登入成功! 222 #>>>2.0001063346862793 # >>>login_in # >>>登入验证
有参装饰器
应用原因
# 由于语法糖的限制,outter函数只能有一个参数,并且函数知识用来接收被修饰对象的内存地址 def outter(func): # outter 的参数也不能改动 def wrapper(*args,**kwargs): # wrapper的参数不能改动 res = func(*args,**kwargs) return res return wrapper
如果outter需要接受多个参数时,在无参装饰器的基础上再套一层,为被装饰对象多传值
def auth(a,b,c): def outter(func): # outter 的参数也不能改动 def wrapper(*args,**kwargs): # wrapper的参数不能改动 res = func(*args,**kwargs) return res return wrapper return outter @auth(a = 111, b = 222, c = 333) def logn_in(x): pass
多个装饰器:
加载顺序是自下而上的;执行顺序是自上而下的。
五.迭代器
是指迭代(是一个重复的过程)取值的工具,基于上一次结果而继续的,单纯的重复不是迭代。
可迭代对象:但凡内置方法中有__iter__方法的都称为可迭代对象
迭代器对象:有__iter__()同时有__next__()方法
迭代器适用所有类型:(字符串、列表、字典、元组、集合、文件)
a = 'afsafacasd' a_iterator = a.__iter__() # 迭代器 while True: try: print(a_iterator.__next__()) except StopIteration: break
以下代码与上面的功能一样:
1.调出a.__iter__(),得到一个迭代器
2.调出迭代器下面的__next__()方法,拿到一个返回值赋值给k。
3.循环步骤2,直到异常出现,跳出循环。
a = 'afsafacasd' for k in a: print(k)
总结:
优点:①为序列和非序列类型提供了一种统一的取值方法;②惰性计算:迭代器对象表示的是一个数据流,可以只在需要时才去调用next来计算出一个值,就迭代器本身来说,同一时刻在内存中只有一个值,因而可以存放无限大的数据流,而对于其他容器类型,如列表,需要把所有的元素都存放于内存中,受内存大小的限制,可以存放的值的个数是有限的。
缺点:①除非取尽,否则无法获取迭代器的长度;②一次只能取一个值,如果取完了,需要重新调用迭代器才能够继续取值。
六、生成器
本质就是迭代器;是自定义的迭代器
def func(): print('第一次') yield 1 # yield 函数在运行时,遇到yield会停下来,
#将yield后面的值当做本次的调用结果返回 print('第二次') yield 2 print('第三次') yield 3 print('第四次') yield 4 g=func() res = next(g) print(res)
yield作为表达式的用法:
def dog(y): print('狗狗%s准备吃东西了'%y) while True: x = yield # yield 接收到的是send的过来的值,
# 但是一开始的时候必须send(None) print('狗狗%s吃了%s'%(y,x)) g = dog('小黑') g.send(None) g.send('包子') g.send('饼干') g.send('骨头')
七、三元表达式
语法格式: 条件成立返回的值 if 条件 else 条件不成立返回的值
列表生成式:l = [表达式 for i in 可迭代对象 if 条件]