Python从零开始 day9-装饰器-1
装饰器:
作用域 , 高阶函数, 闭包
闭包:在一个内部函数里,对一个外部作用域进行引用,那么这个内部函数被认为是闭包
def f(): x = 5 def fo(): # 内部函数 print(x) # 5 x是外部环境的变量 return fo # fo()就是一个闭包 f()() foo= f() # 不能直接调用fo()函数,局部变量,全局变量无法调用 foo()
关于闭包,就是一个内部函数加一个外部环境变量
一个简单的装饰器
import time def func(): start = time.time() # 获取当前时间 print('ABC') time.sleep(0.05) # 停留时间 end = time.time() print(end-start) func()
带有返回值的装饰器
def timmer(f): # 装饰器函数 def inner(): start = time.time() ret = f() # 被装饰的函数 end = time.time() print(end-start) return ret return inner @timmer # 语法糖 @装饰器函数名 def func(): # 被装饰的函数 time.sleep(0.01) print('大家好!') return '新年好!' # func = timmer(func) # 相当于是@timmer ret = func() # inner() 实际上inner()的调用函数是f();也就是func()--->inner()---->f() print(ret)
装饰器的作用:不想修改函数的调用方式,但是还想在原来的函数前后添加功能
原则:开放封闭原则
1、装饰带有参数的实例:
import time def timmer(f): def inner(a): start = time.time() ret = f(a) end = time.time() return ret return inner @timmer # func()=timmer(func) def func(a): time.sleep(0.01) print('大家好!',a) # 大家好! 1 return '新年好!' ret = func(1) # func()---->inner()---->f(),对func()传参数也要对inner和f传参数 print(ret) # 新年好!
2、传动态参数的实例:
import time def timmer(f): def inner(*args,**kwargs): start = time.time() ret = f(*args,**kwargs) end = time.time() return ret return inner @timmer # func()=timmer(func) def func(a,b): time.sleep(0.01) print('大家好!',a,b) # 大家好! 1 2 return '新年好!' def func1(a,c=3): time.sleep(0.01) print('大家好!',a,c) # 大家好! 1 3 return '新年好!' ret = func(1,2) # func()---->inner()---->f(),对func()传参数也要对inner和f传参数 ret1 = func1(1) print(ret) # 新年好!
总结:最简单的装饰器----->带有返回值的----->带有一个参数的----->带有动态参数的(万能参数的)
装饰器的固定模式:
def wrapper(f): # wrapper为装饰的意思,f为被装饰的函数 def inner(*args,**kwargs): # 在装饰函数之前要做的事 ret = f(*args,**kwargs) # 在装饰函数之后要做的事 return ret return inner @wrapper def func(): # print('大家好!') return '新年好!' ret = func() print(ret)