Python-装饰器 decorators

菜鸟教程-Python 函数装饰器

1. 在函数中返回函数

  1. def hi(name="tl"):
  2. def greet():
  3. return "now you are in the greet() function"
  4. def welcome():
  5. return "now you are in the welcome() function"
  6. if name == "tl":
  7. return greet
  8. else:
  9. return welcome
  10. a = hi()
  11. print(a)
  12. print(a())
  13. # <function hi.<locals>.greet at 0x00000264BDCAA0D0>
  14. # now you are in the greet() function

注意:在返回的时候返回函数名welcome而非welcome(),否则会返回函数的返回值

2. 将函数作为参数传递

  1. def hi():
  2. return "hi tl"
  3. def doSomeThingBeforeHi(func):
  4. print("Im in front of Hi!")
  5. print(func())
  6. doSomeThingBeforeHi(hi)
  7. # Im in front of Hi!
  8. # hi tl

可以看到传递进去了hi()

3. 装饰器

3.1 第一个装饰器

使用装饰器,可以在一个函数的前后执行代码

  1. def a_new_decorator(a_func):
  2. def wrapTheFunction():
  3. print("I am doing some boring work before executing a_func()")
  4. a_func()
  5. print("I am doing some boring work after executing a_func()")
  6. return wrapTheFunction
  7. def a_function_requring_decoration():
  8. print("I am the function which needs some decoration to remove my foul smell")
  9. a_function_requring_decoration()
  10. a_function_requring_decoration = a_new_decorator(a_function_requring_decoration)
  11. a_function_requring_decoration()
  12. # I am the function which needs some decoration to remove my foul smell
  13. # I am doing some boring work before executing a_func()
  14. # I am the function which needs some decoration to remove my foul smell
  15. # I am doing some boring work after executing a_func()

3.2 使用’@‘来生成一个装饰器

  1. def a_new_decorator(a_func):
  2. def wrapTheFunction():
  3. print("I am doing some boring work before executing a_func()")
  4. a_func()
  5. print("I am doing some boring work after executing a_func()")
  6. return wrapTheFunction
  7. @a_new_decorator
  8. def a_function_requring_decoration():
  9. print("I am the function which needs some decoration to remove my foul smell")
  10. a_function_requring_decoration()

@a_new_decorator其实和a_function_requring_decoration = a_new_decorator(a_function_requring_decoration)是相同意思

3.3 装饰器的方法名

按照3.2的方法构建装饰器后,如果我们打印方法名,会出现如下问题:

  1. print(a_function_requring_decoration.__name__)
  2. # wrapTheFunction

这里的函数被warpTheFunction替代了。它重写了我们函数的名字和注释文档(docstring)。我们可以使用functools.wraps解决这一问题

  1. from functools import wraps
  2. def a_new_decorator(a_func):
  3. @wraps(a_func)
  4. def wrapTheFunction():
  5. print("I am doing some boring work before executing a_func()")
  6. a_func()
  7. print("I am doing some boring work after executing a_func()")
  8. return wrapTheFunction
  9. @a_new_decorator
  10. def a_function_requiring_decoration():
  11. print("I am the function which needs some decoration to "
  12. "remove my foul smell")
  13. print(a_function_requiring_decoration.__name__)
  14. # a_function_requiring_decoration

3.4 装饰器蓝本规范

  1. from functools import wraps
  2. def decorator_name(f):
  3. @wraps(f)
  4. def decorated(*args, **kwargs):
  5. if not can_run:
  6. return "Function will not run"
  7. else:
  8. return f(*args, **kwargs)
  9. return decorated
  10. @decorator_name
  11. def func():
  12. return("Function is running")
  13. can_run = True
  14. print(func())
  15. can_run = False
  16. print(func())

4. 类装饰器

  1. class decorator_class(object):
  2. def __init__(self, func):
  3. self._func = func
  4. print("class decorator initing")
  5. def __call__(self):
  6. print("class decorator running")
  7. self._func()
  8. print("class decorator ending")
  9. @decorator_class
  10. def func():
  11. print("function!")
  12. print("----------------------")
  13. func()
  14. # class decorator initing
  15. # ----------------------
  16. # class decorator running
  17. # function!
  18. # class decorator ending