1、装饰器
专业解释简介:python用特殊的语法来表示装饰器(decorator),这些装饰器可以用来修饰函数。对于受到封装的原函数来说,装饰器能够在那个函数执行之前以及执行完毕之后,分别运行一些附加代码。这使得开发者可以在装饰器里面访问访问并修改原函数的参数及及返回值,以实现约束语义、调试程序、注册函数等目标。
个人理解:对原有函数进行二次封装,实现原函数没有的附加功能
使用:定义好装饰器函数,使用@符号来修饰函数,作用相当于在装饰器内部调用装饰的那个函数
2、代码
- 给装饰器不传递参数
from functools import wraps
def trace(func):
@wraps(func)
def wrapper(*args, **kwargs):
result = func(*args, **kwargs)
print('%s(%r, %r) -> %r' % (func.__name__, args, kwargs, result)) # 重点:%r为万能格式化字符串
return result
return wrapper
@trace
def fibonacci(n):
if n in (0, 1):
return n
return fibonacci(n - 2) + fibonacci(n - 1)
if __name__ == '__main__':
fibonacci(3)
print(fibonacci)
输出结果:
fibonacci((1,), {}) -> 1
fibonacci((0,), {}) -> 0
fibonacci((1,), {}) -> 1
fibonacci((2,), {}) -> 1
fibonacci((3,), {}) -> 2
<function fibonacci at 0x00000000025777B8>
注意:如果不使用@wraps,会使被装饰的函数对于内置的help函数失效,使用print函数打印被装饰的函数,显示的函数名字也会不一样,还会导致其余一些难以排查的问题。因此,我们需要使用wraps来保证装饰后的函数具备正确的行为。
以下是没有使用wraps函数做处理显示的结果:
print(fibonacci)
>>> <function trace.<locals>.wrapper at 0x00000000023A77B8>
help(fibonacci)
>>> Help on function wrapper in module __main__:
wrapper(*args, **kwargs)
# @wraps(func)
- 给装饰器传递参数
from functools import wraps
def verify_data(name=""):
# 对参数做外层校验
print(name)
def get_result(func):
@wraps(func)
def re_wraps(*args, **kwargs):
result = func(*args, **kwargs)
print('%s(%r, %r) -> %r' % (func.__name__, args, kwargs, result))
return result
return re_wraps
return get_result
@verify_data('add')
def add():
return 1 + 1
print(add())
3、在这里顺便说一下闭包
装饰器就是由闭包实现的,闭包必须满足的三个条件
- 必须是一个嵌套的函数。
- 闭包必须返回嵌套函数。
- 嵌套函数必须引用一个外部的非全局的局部自由变量。
闭包函数的优点:
- 避免使用全局变量
- 可以提供部分数据的隐藏
- 可以提供更优雅的面向对象实现