Python之闭包 装饰器
函数的闭包
1. 函数的嵌套调用
def func(): print(123) def func2(): func() print(234) func2()
2. 函数的嵌套定义
def func(): print(123) def func2(): print(234) func2() # 只能在func里面调用func2 func()
3. 闭包
a. 闭包本质就是一种函数
b. 使用闭包一定会使用到嵌套函数
c. 闭包的意义:在变量不被别人调用的时候,最大的节省空间
d. 内部函数引用了外部函数的变量,内部函数就叫闭包
def func(): name = "chita" def inner(): # inner就是闭包函数 print(name) print(inner.__closure__) # 检测是不是闭包,是的话打印(<cell at 0x000001F9F5760108: str object at 0x000001F9F58564C8>,) 不是的话打印 none ret = func() ret()
装饰器
1. 装饰器其本质就是闭包,是特殊的闭包函数
def func(): def inner(): # inner是闭包 print('inner') return inner # 整个func函数就是装饰器
2. 装饰器的作用
a. 在一个函数的前后添加功能,不能修改函数的信息,并且对于用户感知不到装饰器的存在
b. 开放封闭原则, 即扩展是开放的,修改是封闭的
3. 常见装饰器
a. 被装饰函数没有参数
import time def timmer(func): def inner(): start = time.time() func() end = time.time() print(end-start) return inner @timmer # 语法糖 其本质就是先执行 qqxing = timmer(qqxing),然后执行qqxing() def qqxing(): # 被装饰的函数 for i in range(10000000):pass print("老板万岁") qqxing()
b. 被装饰函数有参数
import time def timmer(func): def inner(*args,**kwargs): start = time.time() ret = func(*args,**kwargs) #qqxing end = time.time() print(end-start) return ret return inner @timmer # 语法糖 等价于qqxing = timmer(qqxing) def qqxing(num1,num2): # 被装饰的函数 for i in range(10000000):pass print("老板万岁") return num1,num2 ret = qqxing(2,5) print(ret)
c. 最简单的装饰器
def wrapper(func):#装饰器 def inner(*args,**kwargs): print("被装饰的函数执行之前你要做的事") ret = func(*args,**kwargs) #func是被装饰的函数 :参数,返回值 print("被装饰的函数执行之后你要做的事") return ret return inner
d. 带参数的装饰器
FLAG = False def log(flag): def wrapper(func): def inner(*args,**kwargs): if flag: print("call :%s"%func.__name__) ret = func(*args,**kwargs) return ret return inner return wrapper @log(FLAG) # @和log(FLAG)是分开执行的,一般都是从后往前执行 # 执行流程: wrapper =log(FLAG) # @wrapper-->qqxing = wrapper(qqxing)--->qqxing=inner def qqxing(): print("qqxing") qqxing() # qqxing()=inner()
e. 嵌套装饰器
def wrapper1(func): def inner1(): print('wrapper1 ,before func') func() # f print('wrapper1 ,after func') return inner1 def wrapper2(func): def inner2(): print('wrapper2 ,before func') func() # inner1 print('wrapper2 ,after func') return inner2 @wrapper2 # f = wrapper2(wrapper1(f)) --> f = wrapper2(inner1) --> f = inner2 @wrapper1 # 谁先被调用的谁在外边,一般都是从后往前执行 def f(): print('in f') f() # inner2()
结果:
now in wrapeer2,before func
now in wrapeer1,before func
now in func
after func 1
after func 2
分析:
当程序运行到上面两句的时候只是执行了以下几步:
首先执行的是@wrapper1---->func=wrapper(func)
然后等到执行的@wrapper2,此时的func=wrapper(func),所以这步的结果是func=wrapper2(wrapper1(func))
执行到func()的时候:
func()被调用,此时的func=wrapper2(wrapper1(func))的结果是func=inner2,所以func()等价于inner2()
在inner2函数中,执行到func()的时候,此时的func=wrapper(func),即func=inner1,所以此时调用的是inner1()
在inner1函数中,执行到func()的时候,此时的func=func,所以是执行func()自己,
inner1执行完毕后,回到inner2中继续执行,然后结束