(修饰器本身也是个高阶函数)


修饰器

修饰器本身有点类似于模板, 函数“被修饰”成功能更健全的函数, 修饰器本质上属于闭包函数

  1. # 示例1(修饰器实现原理)
  2. # =========================================
  3. # 修饰器函数
  4. def decorator(f):
  5. print("this is decorator")
  6. return f()
  7. # 被修饰函数
  8. def function():
  9. print("function")
  10. return 0
  11. print( decorator(function) )

使用上述的方法使得函数本身不易读,如果函数还须更加麻烦的操作, 这时,修饰器就登场了

基本语法

  1. 修饰器基本语法
  2. # =========================================
  3. # 修饰器函数
  4. import functools # 导入函数工具模块
  5. def decorator(f): # 修饰器函数
  6. @functools.wraps(f) # 拷贝“被修饰”函数的全部属性
  7. def inside_function():
  8. pass # “函数体”(根据需求合理是指)
  9. return f() # 修饰过后函数的返回值(根据需求合理设置)
  10. return inside_function
  11. @decorator # 修饰器
  12. def function(): # 被修饰函数
  13. pass
  14. return 0
  15. function() # 使用被修饰过后的函数
  16. # =========================================
  17. # 说明
  18. pass :修饰需要添加的语句
  19. return f() :返回被修饰函数的返回值
  20. decorator :修饰器函数名
  21. @ :修饰器关键字
  22. @decorator :修饰器
  23. @functools.wraps(f) :拷贝被修饰函数中的所有属性
  24. import functools :需要用到的模块
  1. # 示例2(修饰器案例)
  2. # =========================================
  3. import functools
  4. def decorator(f):
  5. @functools.wraps(f)
  6. def inside_function():
  7. print("Dectorator")
  8. return f()
  9. return inside_function
  10. @decorator
  11. def fun():
  12. print("function")
  13. return 0
  14. print( fun() )
  15. # =========================================
  16. 输出
  17. this is decorator
  18. function
  19. 0

拷贝原函数属性

functools.wraps:是functools中的一个模块,作用是拷贝函数属性 例如把被修饰函数中的__name__属性拷贝到修饰器函数中 就不需要通过decorator.__name__=function.__name__的方式来实现 如果不这样操作,修饰器修饰过后,会变成“另外一个函数”

  1. import functools
  2. def decorator(f):
  3. @functools.wraps(f) # 拷贝function中的所有属性到修饰器中
  4. def inside():
  5. print(f.__name__) # 检测修饰函数的—__name__属性
  6. return f()
  7. return inside
  8. @decorator
  9. def function():
  10. print(function.__name__)# 检测“被修饰”函数的—__name__属性
  11. function()
  12. # =========================================
  13. 输出
  14. function
  15. function
  1. import functools
  2. def decorator(f):
  3. #@functools.wraps(f) # 关闭拷贝
  4. def inside():
  5. print(f.__name__) # 检测修饰函数的—__name__属性
  6. return f()
  7. return inside
  8. @decorator
  9. def function():
  10. print(function.__name__)# 检测“被修饰”函数的—__name__属性
  11. function()
  12. # =========================================
  13. 输出
  14. function
  15. inside

带参修饰器

如果希望修饰器能够带参数,就必须再套一层函数 基础修饰器要两层函数 带参数修饰器要三层函数

  1. import functools
  2. def decorator(value):
  3. print("print ",value)
  4. def inside_decorator(f):
  5. @functools.wraps(f)
  6. def inside_function():
  7. return f()
  8. return inside_function
  9. return inside_decorator
  10. @decorator("decorator") # 修饰器函数也可以接受参数了
  11. def function():
  12. print("function")
  13. function()

传递参数

修饰器中的参数必须和“被修饰”函数的参数保持一致

  1. import functools
  2. def decorator(f):
  3. @functools.wraps(f)
  4. def inside(a, b): # inside()中的参数必须和,“被修饰”函数 function的参数保持一致
  5. print("insdie():",a, b)
  6. return f(a,b)
  7. return inside
  8. @decorator
  9. def function(a,b):
  10. print("function():",a,b)
  11. function("string","str")
  12. # =========================================
  13. 输出
  14. insdie(): string str
  15. function(): string str

但是在实际操作中,修饰器只有一个,而被修饰函数可以有无数个, 根据被修饰函数的功能不同,会有不一样的参数,这种情况下我们没办法要求所有的函数都有统一的参数

此时修饰器就可以使用,不定参数和拆包来解决这个问题

  1. import functools
  2. def decorator(f):
  3. @functools.wraps(f)
  4. def inside(*c): # 定义函数时,使用*可以作为不定参数
  5. print("insdie():",*c) # 调用参数时,使用*可以进行拆包
  6. return f(*c)
  7. return inside
  8. @decorator
  9. def function(a,b):
  10. print("function():",a,b)
  11. @decorator
  12. def func(a):
  13. print("func():",a)
  14. function("string","str")
  15. func("Hibari")
  16. # =========================================
  17. 输出
  18. insdie(): string str
  19. function(): string str
  20. insdie(): Hibari
  21. func(): Hibari