闭包
嵌套函数内,使用非全局非当前空间的变量(自由变量)的就是闭包
代码:
def a():
num = 123
def b():
print(num)
return b
a()()
def c(num):
def d():
print(num)
return d
c(123)()
结果:
123
123
验证是否为闭包
代码:
def a(num):
def b():
print(num)
return b
avg = a(123)
print(avg.__code__.co_freevars) # 查看函数的自由变量
结果:
('num',)
闭包的作用
保存局部信息不被销毁,保证数据的安全性。
闭包的应用
- 可以保存一些非全局变量但是不易被销毁、改变的数据。
- 装饰器
装饰器
开放封闭原则
- 对扩展是开放的
- 对修改是封闭的
什么是装饰器
在不改变原被装饰的函数的源代码以及调用方式下,为其添加额外的功能。
代码:
def a(fun):
def al(*args, **kwargs):
# 装饰前
print("这是装饰前")
num = fun(*args, **kwargs)
# 装饰后
print("这是装饰后")
return num
return al
@a # 语法糖
def b(*args, **kwargs):
print(*args, **kwargs)
b(123)
结果:
这是装饰前
123
这是装饰后
对语法糖进行拆解
代码:
def a(fun):
def al(*args, **kwargs):
# 装饰前
print("这是装饰前")
num = fun(*args, **kwargs)
# 装饰后
print("这是装饰后")
return num
return al
# @a # 语法糖
# def b(*args, **kwargs):
# print(*args, **kwargs)
#b(123)
def b(*args, **kwargs):
print(*args, **kwargs)
b = a(b)
b(123)
结果:
这是装饰前
123
这是装饰后
有参装饰器
代码:
def al(num): # 参数
def a2(b1):
def a3(*args,**kwargs):
if num: # 判断传入的参数
return b1(*args,**kwargs)
else:
print("Flase")
return a3
return a2
@al(1) # 传参
def bl(*args,**kwargs):
return "bl"
print(bl())
结果:
bl
多个装饰器装饰一个函数
优先执行最近的装饰器
代码:
def a1(fun):
def a2():
print("a1装饰器前") # 第二步
fun() # 第五步
print("a1装饰器后") # 第七步
return a2
def b1(fun):
def b2():
print("b1装饰器前") # 第三步
fun() # 第四步
print("b1装饰器后") # 第六步
return b2
@a1
@b1
def c():
print("函数c") # 第五步
c() # 第一步
结果:
a1装饰器前
b1装饰器前
函数c
b1装饰器后
a1装饰器后
functools.wrap
使用functools.wrap
后会保留函数的元数据(函数名/注释)
代码:
import functools
def wrapper(func):
@functools.wraps(func)
def wrapper():
print 'before'
func()
print 'after'
return wrapper
@wrapper
def foo():
print 'foo'