一、闭包
1. 作用
内部函数保存外部函数的参数
2.闭包定义
- 函数嵌套
- 内部函数使用外部函数的参数
- 外部函数返回了内部函数
3.代码格式
def func_out(num1):
def func_inner(num2):
num = num1+num2
return num
return func_inner
f = func_out(10)
print(f(1))
print(f(2))
4.内部函数修改外部函数变量
def func_out(num1):
def func_inner(num2):
# 这里声明num1,是外部函数变量
nonlocal num1
# 如果不声明nonlocal,则会创建局部变量num1
num1 = num1 + num2
return num1
print(num1)
func_inner(10)
print(num1)
return func_inner
func_out(10)
二、装饰器
1. 作用
- 给已有函数增加额外功能的函数,它本质上就是一个闭包函数
- 装饰器的功能特点:
- 不修改已有函数的源代码
- 不修改已有函数的调用方式
- 给已有函数增加额外的功能
2.代码实现
def check(f):
def inner():
print('开始验证')
f()
print('登陆成功')
return inner
@check
def login():
print('开始登陆!')
login()
# 注意:@check等价于 login = check(login)
3.多个装饰器,返回值和不定长参数
def check1(f):
def inner(*args, **kwargs):
print('校验1开始!')
result = f(*args, **kwargs)
print('校验1结束!')
return result
return inner
def check2(f):
def inner(*args, **kwargs):
print('校验2开始!')
# 这里接收 不定长参数,并用result接收返回值
result = f(*args, **kwargs)
print('校验2结束!')
return result
return inner
@check1
@check2
def login(*args, **kwargs):
# *args,**kwargs , 其中args是元组,kwargs是dict
# */** 的作用是解包
print(args, kwargs)
print('开始登陆!')
# print(*args, **kwargs)
return
login(1,2,3, name='aaa',age=123)
# 输出结果:
# 校验1开始!
# 校验2开始!
# (1, 2, 3) {'name': 'aaa', 'age': 123}
# 开始登陆!
# 校验2结束!
# 校验1结束!
4. 装饰器传参
通过参数,使装饰器更通用(可以根据不同参数,实现不同功能)
def func(a, b):
def logging(f):
def inner():
if a == '1':
print('begin:', time.time())
print(b)
f()
print('end:', time.time())
else:
print('---')
f()
print('---')
return inner
return logging
@func('1', '+')
def main():
for i in range(10000):
pass
main()
# 装饰器等价于:
# a = func('1', '+')
# main = a(main)
# main()
5.类装饰器
- 重写__init__方法
- 重写__call__方法
class check():
def __init__(self, f):
self.f = f
def __call__(self, *args, **kwargs):
print('开始校验')
self.f()
print('校验完成')
# 这里等价于 c = check(comment)
@check
def comment():
print('正在评论!')
# 这里等价调用 c(), 即调用对象的__call__方法
comment()