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中继续执行,然后结束
浙公网安备 33010602011771号