了解python中嵌套函数和装饰器的机制



为什么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>'

最新更新