装饰器的形成过程
1.函数无参数,无返回值
import time def f1(): # 无参数,无返回值 time.sleep(1) print("Hello, World!") def timer(f): # f 是函数名 def inner(): # 闭包 start = time.time() f() end = time.time() total = end - start print(total) return inner f1 = timer(f1) # 调用timer()函数,获取inner函数名指向的内存地址的返回值 f1()
2.函数有返回值,无参数
import time def f1(): # 无参数,有返回值 time.sleep(1) print("Hello, World!") return True def timer(f): # f 是函数名 def inner(): # 闭包 start = time.time() ret = f() end = time.time() total = end - start print(total) return ret return inner f1 = timer(f1) # 调用timer()函数,获取inner函数名指向的内存地址的返回值 ret = f1() print(ret)
3.函数有参数,有返回值
def f1(a, **kwargs): # 参数,返回值 *args和**args可以组成任意类型的参数 time.sleep(1) print("Hello, World!", a, kwargs) return "abc" def timer(f): # f 是函数名 def inner(*args, **kwargs): # 闭包 start = time.time() ret = f(*args, **kwargs) end = time.time() total = end - start print(total) return ret return inner f1 = timer(f1) # 调用timer()函数,获取inner函数名指向的内存地址的返回值 ret = f1(1, name='tom') print(ret)
装饰器的作用
在不改变函数调用方式的情况下,在原函数的前后添加功能
开放封闭原则
开放:对扩展开放
封闭:对修改封闭
语法糖
简化代码
import time def timer(f): # f 是函数名 def inner(*args, **kwargs): # 闭包 start = time.time() ret = f(*args, **kwargs) end = time.time() total = end - start print(total) return ret return inner @timer # f1 = timer(f1),语法糖简化代码 def f1(a, **kwargs): # 参数,返回值 *args和**args可以组成任意类型的参数 time.sleep(1) print("Hello, World!", a, kwargs) return "abc" ret = f1(1, name='tom') print(ret)
装饰器的固定模式
def wrapper(f): # f是被装饰的函数 def inner(*args, **kwargs): # 在原函数(被装饰)前增加的功能 ret = f(*args, **kwargs) # f是被装饰的函数 # 在被装饰的函数后增加的功能 return ret return inner @wrapper # 语法糖,实质 f1 = wrapper(f1) def f1(): print("Hello, World!") f1() # f1函数名指向的内存地址是:inner的函数名
巧记:1.先定义函数,再定义内部函数,返回内部函数的函数名
2.内部函数内放被装饰的函数,传进被装饰函数的函数名
3.被装饰的参数需要参数和返回值