我正在尝试了解装饰装饰器,并想尝试以下内容:
假设我有两个装饰器并将它们应用于函数hello:
def wrap(f):
def wrapper():
return " ".join(f())
return wrapper
def upper(f):
def uppercase(*args, **kargs):
a,b = f(*args, **kargs)
return a.upper(), b.upper()
return uppercase
@wrap
@upper
def hello():
return "hello","world"
print hello()
然后我必须开始为其他功能添加其他装饰器, 但一般情况下,wrap装饰器将“包裹所有这些”
def lower(f):
def lowercase(*args, **kargs):
a,b = f(*args, **kargs)
return a.lower(), b.lower()
return lowercase
@wrap
@lower
def byebye():
return "bye", "bye"
现在我该如何编写一个装饰器,我可以装饰我的下装饰器和上装饰器:
@wrap
def lower():
...
@wrap
def upper():
...
仅通过以下方式获得与上述相同的结果:
@upper
def hello():
...
@lower
def byebye():
...
答案 0 :(得分:23)
def upper(f):
@wrap
def uppercase(*args, **kargs):
a,b = f(*args, **kargs)
return a.upper(), b.upper()
return uppercase
Python中的装饰器
@foo
def bar(...): ...
等同于
def bar(...): ...
bar = foo(bar)
你想获得
的效果@wrap
@upper
def hello(): ....
即
hello = wrap(upper(hello))
所以wrap
应该在upper
的返回值上调用:
def upper_with_wrap(f):
def uppercase(...): ...
return wrap(uppercase)
这也等同于在该函数上应用装饰器:
def upper_with_wrap(f):
@wrap
def uppercase(...): ...
# ^ equivalent to 'uppercase = wrap(uppercase)'
return uppercase
答案 1 :(得分:8)
这是一个用装饰器装饰装饰器的通用(并且有点复杂)解决方案(耶!)。
# A second-order decorator
def decdec(inner_dec):
def ddmain(outer_dec):
def decwrapper(f):
wrapped = inner_dec(outer_dec(f))
def fwrapper(*args, **kwargs):
return wrapped(*args, **kwargs)
return fwrapper
return decwrapper
return ddmain
def wrap(f):
def wrapper():
return " ".join(f())
return wrapper
# Decorate upper (a decorator) with wrap (another decorator)
@decdec(wrap)
def upper(f):
def uppercase(*args, **kargs):
a,b = f(*args, **kargs)
return a.upper(), b.upper()
return uppercase
@upper
def hello():
return "hello","world"
print hello()