https://zhuanlan.zhihu.com/p/21696291
https://www.zhihu.com/search?type=content&q=python%20%E8%A3%85%E9%A5%B0%E5%99%A8
一、装饰器
装饰器:装饰器实质上是一个函数,它把一个函数作为输入(参数)并且返回相同的函数,在这中间执行了其他的代码。其实就是闭包概念的深化。装饰器就是为已经存在的函数提供额外的功能
def document_it(func):
def new_function(*args, **kwargs):
print('Running function:', func.__name__)
print('Positional arguments:', args)
print('Keyword arguments:', kwargs)
result = func(*args, **kwargs)
print('document_it Result:', result)
return result
return new_function
这里定义了一个装饰器,往函数 document_it
传入一个函数 func
,然后在document_it
里定义一个 new_function
函数,该函数一方面有其自己的逻辑,另一方面也撩了撩 func:result = func(*args, **kwargs)
,请记住,这里是确实调用了 func
。最后,将整个 new_function
返回给外部了,这个 new_function
从模糊概念上来讲,是个闭包,如“预备知识”里讲的,它不是该函数执行结果。
def use_logging(func):
def wrapper(*args, **kwargs):
logging.warn("%s is running" % func.__name__)
return func(*args)
return wrapper
@use_logging
def foo():
print("i am foo")
@use_logging
def bar():
print("i am bar")
最后返回的就是目标函数,通过位置参数可以根据目标函数实现多元传参;
带参数的装饰器:也就是在外层又包裹了一个带参数的函数,最终都是返回目标函数:
def use_logging(level):
def decorator(func):
def wrapper(*args, **kwargs):
if level == "warn":
logging.warn("%s is running" % func.__name__)
return func(*args)
return wrapper
return decorator
@use_logging(level="warn")
def foo(name='foo'):
print("i am %s" % name)
有多个装饰器时,从最靠近目标函数的装饰器开始执行:
@a
@b
@c
def f ():
等效于
f = a(b(c(f)))