(修饰器本身也是个高阶函数)
修饰器
修饰器本身有点类似于模板, 函数“被修饰”成功能更健全的函数, 修饰器本质上属于闭包函数
# 示例1(修饰器实现原理)# =========================================# 修饰器函数def decorator(f):print("this is decorator")return f()# 被修饰函数def function():print("function")return 0print( decorator(function) )
使用上述的方法使得函数本身不易读,如果函数还须更加麻烦的操作, 这时,修饰器就登场了
基本语法
修饰器基本语法# =========================================# 修饰器函数import functools # 导入函数工具模块def decorator(f): # 修饰器函数@functools.wraps(f) # 拷贝“被修饰”函数的全部属性def inside_function():pass # “函数体”(根据需求合理是指)return f() # 修饰过后函数的返回值(根据需求合理设置)return inside_function@decorator # 修饰器def function(): # 被修饰函数passreturn 0function() # 使用被修饰过后的函数# =========================================# 说明pass :修饰需要添加的语句return f() :返回被修饰函数的返回值decorator :修饰器函数名@ :修饰器关键字@decorator :修饰器@functools.wraps(f) :拷贝被修饰函数中的所有属性import functools :需要用到的模块
# 示例2(修饰器案例)# =========================================import functoolsdef decorator(f):@functools.wraps(f)def inside_function():print("Dectorator")return f()return inside_function@decoratordef fun():print("function")return 0print( fun() )# =========================================输出this is decoratorfunction0
拷贝原函数属性
functools.wraps:是functools中的一个模块,作用是拷贝函数属性 例如把被修饰函数中的__name__属性拷贝到修饰器函数中 就不需要通过decorator.__name__=function.__name__的方式来实现 如果不这样操作,修饰器修饰过后,会变成“另外一个函数”
import functoolsdef decorator(f):@functools.wraps(f) # 拷贝function中的所有属性到修饰器中def inside():print(f.__name__) # 检测修饰函数的—__name__属性return f()return inside@decoratordef function():print(function.__name__)# 检测“被修饰”函数的—__name__属性function()# =========================================输出functionfunction
import functoolsdef decorator(f):#@functools.wraps(f) # 关闭拷贝def inside():print(f.__name__) # 检测修饰函数的—__name__属性return f()return inside@decoratordef function():print(function.__name__)# 检测“被修饰”函数的—__name__属性function()# =========================================输出functioninside
带参修饰器
如果希望修饰器能够带参数,就必须再套一层函数 基础修饰器要两层函数 带参数修饰器要三层函数
import functoolsdef decorator(value):print("print ",value)def inside_decorator(f):@functools.wraps(f)def inside_function():return f()return inside_functionreturn inside_decorator@decorator("decorator") # 修饰器函数也可以接受参数了def function():print("function")function()
传递参数
修饰器中的参数必须和“被修饰”函数的参数保持一致
import functoolsdef decorator(f):@functools.wraps(f)def inside(a, b): # inside()中的参数必须和,“被修饰”函数 function的参数保持一致print("insdie():",a, b)return f(a,b)return inside@decoratordef function(a,b):print("function():",a,b)function("string","str")# =========================================输出insdie(): string strfunction(): string str
但是在实际操作中,修饰器只有一个,而被修饰函数可以有无数个, 根据被修饰函数的功能不同,会有不一样的参数,这种情况下我们没办法要求所有的函数都有统一的参数
此时修饰器就可以使用,不定参数和拆包来解决这个问题
import functoolsdef decorator(f):@functools.wraps(f)def inside(*c): # 定义函数时,使用*可以作为不定参数print("insdie():",*c) # 调用参数时,使用*可以进行拆包return f(*c)return inside@decoratordef function(a,b):print("function():",a,b)@decoratordef func(a):print("func():",a)function("string","str")func("Hibari")# =========================================输出insdie(): string strfunction(): string strinsdie(): Hibarifunc(): Hibari
