函数闭包:
概念:函数内部嵌套函数,并且外部函数返回内部函数,嵌套函数用到外部函数的局部变量,嵌套函数+局部变量=闭包
def a1(): a=1 def a2(): nonlocal a #如果不加这一句,下一句会报错,说a未定义,但是如果下一句用b=a+1 这时候可以不用添加 a = a + 1 print(f"a2的a都是{a}") print(f"a1的a都是{a}") return a2 x=a1()() 输出如下: a1的a都是1 a2的a都是2
a2() 和a变量一起组成了闭包
装饰器
装饰器:本质就是函数,返回内部函数,内部函数有调用函数的接口,功能是为其他函数添加附加功能=高级函数+闭包+函数嵌套
原则:
1、不修改原函数的调用方式
2、不修改原函数的源代码
返回值问题:最后返回的是嵌套函数的返回值,不是原函数的返回值
@timer 装饰器问题,即使没有test(),他也会运行
#运行test() 相当于运行wrapper(),所以是wrapper的返回值
import time
def timer(func):
def wrapper(*args, **kwargs):
start_time= time.time()
print("wrapper开始了。")
# f_res = func(*args, **kwargs) # 如果运行注释的函数,这样可以返回原函数的返回值
func(*args, **kwargs)
end_time= time.time()
print("wrapper结束: 共用时间:%d秒" %(end_time - start_time))
return "这是wrapper的返回值"
# return f_res
return wrapper
@timer #相当于test = timer(test) ####这一步编译的时候就运行了 即使没有test() 这一个也会运行
def test(*args, **kwargs):
print("test 开始运行")
time.sleep(3)
return '这是test的返回值'
res = test()
print(res)
#输出如下: wrapper开始了。 test 开始运行 wrapper结束: 共用时间:3秒 这是wrapper的返回值
解包
a,*d,c=[1,2,3,4,5,6] a是1 c是6,中间的全部弄到d中了 ,但是*后面必须跟个变量名
a,b=b,a 交换a,b的值
可选择的修饰器
就在原来修饰器外面添加个选择函数
import time def consumption(func): print("消费开始:") def inner(*args, **kwargs): print("内部消费开始:") res = func(*args, **kwargs) print("内部消费结束") return res return inner @consumption def chifan(): time.sleep(3) print("我吃完饭了,用来3秒") @consumption def read_book(): time.sleep(0.5) print("我读完书了,用了0.5") chifan() #输出如下: 两个消费开始说明,先运行了两次@consumption 消费开始: 消费开始: 内部消费开始: 我吃完饭了,用来3秒 内部消费结束
import time
def cons(select=1): #在原来外面添加一个选择函数
def consumption(func):
print("消费开始:")
def inner(*args, **kwargs):
if select == 1:
print("内部消费1开始:")
res = func(*args, **kwargs)
print("内部消费1结束")
return res
elif select == 2:
print("内部消费2开始:")
res = func(*args, **kwargs)
print("内部消费2结束")
return res
return inner
return consumption
@cons(2) #这里可以选择消费类型
def chifan():
time.sleep(3)
print("我吃完饭了,用来3秒")
@cons(1) #这里可以选择消费类型
def read_book():
time.sleep(0.5)
print("我读完书了,用了0.5")
chifan()
read_book()
#输出如下:
消费开始:
消费开始:
内部消费2开始:
我吃完饭了,用来3秒
内部消费2结束
内部消费1开始:
我读完书了,用了0.5
内部消费1结束
多重修饰器
def dec1(func):
print("HHHA:0====>")
def one():
print("HHHA:0.1====>")
func()
print("HHHA:0.2====>")
return one
def dec2(func):
print("HHHB:0====>")
def two():
print("HHHB:0.1====>")
func()
print("HHHB:0.2====>")
return two
def dec3(func):
print("HHHC:0====>")
def three():
print("HHHC:0.1====>")
func()
print("HHHC:0.2====>")
return three
@dec1
@dec2
@dec3
def test():
print("HHHD:0====>test")
test()
输出如下:
HHHC:0====>
HHHB:0====>
HHHA:0====>
HHHA:0.1====>
HHHB:0.1====>
HHHC:0.1====>
HHHD:0====>test
HHHC:0.2====>
HHHB:0.2====>
HHHA:0.2====>
组装阶段从下到上 test->dec3->dec2->dec1 执行阶段:one->two->three 调用关系从上到下
函数前阶段,从上到下
函数
函数后阶段:从下到上
def log(text): print("HHHA:0====>") def decorator(func): print("HHHA:0.1====>") def wrapper(*args, **kw): print("HHHA:0.1.1====>") return func(*args, **kw) print("HHHA:0.2====>") return wrapper print("HHHA:1====>") return decorator @log('execute') def now(): print('HHHB:=====>test') now() #输出如下: HHHA:0====> HHHA:1====> HHHA:0.1====> HHHA:0.2====> HHHA:0.1.1====> HHHB:=====>test
先执行含餐部分
再执行装饰器部分
再调用部分