为什么wrapper()可以调用txt但italic()不能(当使用它作为装饰器时)?
如果你能解释事情执行的顺序,以及在包装器中调用fun与调用斜体作为装饰器(例1、2)和不调用斜体(例3)有什么不同,那就很有用了。谢谢!
# EXAMPLE 1: call function with wrapper
def italic(fun):
def wrapper():
return '<i>' + fun() + '</i>'
return wrapper
@italic
def txt():
return 'merp'
print(txt())
Output:
<i>merp</i>
# EXAMPLE 2: call function directly
def italic(fun):
return '<i>' + fun() + '</i>'
@italic
def txt():
return 'merp'
print(txt())
Output:
TypeError: 'str' object is not callable
为什么这里看到txt是字符串?但是如果我尝试return '<i>' + fun + '</i>'
,它说不能将函数连接到字符串lol
edit: nvm,类型错误和不可调用的错误来自两个不同的行;我把他们弄糊涂了><</p>
# EXAMPLE 3: nest functions instead of using as decorator
def italic(fun):
return '<i>' + fun() + '</i>'
def txt():
return 'merp'
print(italic(txt))
Output:
<i>merp</i>
@italic
def func():
...
是语法糖:
func = italic(func)
因此你可以理解这里发生了什么,装饰器是在装饰时执行的。它应该返回另一个可调用对象,因为调用decorator的结果会替换它所装饰的函数。如果你像例子2/3那样做,那么它是用字符串对象txt
替换函数对象txt
,并且函数对象现在被遮蔽(在命名空间中不可用):
>>> def italic(fun):
... return '<i>' + fun() + '</i>'
...
>>> @italic
... def txt():
... return 'merp'
...
>>> txt # this is now a string, not a function. you can't call it.
'<i>merp</i>'
如果你想使用"无闭包"样式装饰器,就像例子2/3,有一个流行的第三方库叫做decorator,它可以帮助你:
>>> from decorator import decorator # pip install decorator
>>> @decorator
... def italic(fun):
... return '<i>' + fun() + '</i>'
...
>>> @italic
... def txt():
... return 'merp'
...
>>> txt()
'<i>merp</i>'