我有点怀疑这是否是装饰器的好用例,但是在这里:
import string
SelfClosing = object()
def escapeAttr(attr):
return attr.replace('"', '\\"')
def tag(name, content='', **attributes):
for attr,value in attributes.items():
assert all(c.isalnum() for c in attr)
attrString = ' '.join('{}="{}"'.format(k,escapeAttr(v)) for k,v in attributes.items())
if not content==SelfClosing:
return '<{name} {attrs}>{content}</{name}>'.format(
name = name,
attrs = attrString,
content = content
)
else:
return '<{name} {attrs}/>'
例子:
def makeBoldWrapper(**attributes):
def wrapWithBold(origFunc):
def composed(*args, **kw):
result = origFunc(*args, **kw)
postprocessed = tag('b', content=result, **attributes)
return postprocessed
return composed
return wrapWithBold
演示:
@makeBoldWrapper(attr1='1', attr2='2')
def helloWorld(text):
return text
>>> print( helloWorld('Hello, world!') )
<b attr2="2" attr1="1">Hello, world!</b>
常见的误解是,参数
(attr1=...)
是装饰器
@myDecorator
的参数;但事实并非如此。相反,函数调用
myDecoratorFactory(attr1=...)
的结果计算为
someresult
并成为一个匿名装饰器
@someresult
。因此,“带参数的装饰器”实际上是需要返回装饰器值的装饰器工厂。
functools.wraps
不会有什么坏处... - Jon Clementsfunctools
装饰器有文档充分解释了它。尽管如此,解释为什么解决方案的结构必须看起来像这样可能是一个好主意。 - millimoosef
是一个以函数g -> ... -> a
作为其参数,并返回一个函数h -> ... -> b
的函数,其中...
是一组任意参数”的概念。 - millimoose