装饰器
程序员文章站
2022-06-30 14:18:23
...
所谓装饰器从字面理解就是,给一个对象添加一些东西。
类似与加工厂的作用,对象进入到一个工厂中,工厂对,"对象“进行处理加工,给“对象”加入新的功能,后输出经过加工后的“对象”。
例:
def use_logging(func):
def wrapper():
logging.warn("%s is running" % func.__name__)
return func() # 把 foo 当做参数传递进来时,执行func()就相当于执行foo()
return wrapper
def foo():
print('i am foo')
foo = use_logging(foo) # 因为装饰器 use_logging(foo) 返回的时函数对象 wrapper,这条语句相当于 foo = wrapper
foo() # 执行foo()就相当于执行 wrapper()
foo = use_logging(foo)
foo()
这太麻烦,我们还可以让写法更简便"语法糖@"
我们可以这样写
def use_logging(func):
def wrapper():
logging.warn("%s is running" % func.__name__)
return func()
return wrapper
@use_logging
def foo():
print('i am foo')
#foo = use_logging(foo)
foo()
@ 符号就是装饰器的语法糖,它放在函数开始定义的地方,这样就可以省略最后一步再次赋值的操作。
>>> def use_logging(func):
def wrapper():
print("%s is running"% func.__name__)
return func()
return wrapper
>>> @use_logging #运行实例@use_logging要写在需要修饰对象的前边
def foo():
print("i am foo")
>>> foo()
foo is running
i am foo
>>> def
@use_logging表示将要修饰下边所定义的对象
填加参数的方式:
def use_logging(func):
def wrapper(name):
print("%s is running"% func.__name__)
return func(name)
return wrapper
@use_logging
def foo(name):
print("hello %s i am foo"% name)
直接将参数传给wrapper就可以了,不过不要忘记返回的func是需要带参数的。
实际上我们还可以让装饰器更加的灵活
def use_logging(level):
def decorator(func):
def wrapper(*args, **kwargs):
if level == "warn":
logging.warn("%s is running" % func.__name__)
elif level == "info":
logging.info("%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)
foo()
上面的 use_logging 是允许带参数的装饰器。它实际上是对原有装饰器的一个函数封装,并返回一个装饰器。我们可以将它理解为一个含有参数的闭包。当我 们使用@use_logging(level=“warn”)调用的时候,Python 能够发现这一层的封装,并把参数传递到装饰器的环境中。
@use_logging(level=“warn”) 等价于 @decorator
上一篇: RxJava基本使用--合并型操作符