这是我的一段代码(Python 3.9.2)
class My_style:
#self.fn = fn
#fn= greet()
def __init__(self,s):
self.s = s
def __call__(self,fn):
self.fn = fn()
if self.s == "upper":
return self.fn.upper()
elif self.s == "bold":
return "<b>" + self.fn + "</b>"
#@My_style("bold")
def greet():
return "Hello World"
decorator = My_style("upper")
greet = decorator(greet) ## This returns the string object instead of function object greet()
greet
'HELLO WORLD'
你得到的不是函数greet(),而是作为greet的字符串。 我不明白为什么它返回一个字符串。
我期待上面的输出与greet()
所以上面的装饰器工作得很好,如果我只是说greet(作为一个字符串)但我希望它工作是greet()(函数调用)
我错过了什么?
添加了它返回一个没有装饰器包装器的函数作为答案中提到的返回(但没有参数化在“上”或“粗体”之间进行选择)
class ToUpper:
def __init__(self, fn): # Decorator
self.fn = fn
def __call__(self): # Wrapper
return self.fn().upper()
def greet():
return "Hello world"
greet = ToUpper(greet) # This returns greet() instead of string
greet()
'HELLO WORLD'
可能参数化调用需要它显式返回函数(在调用方法中)?
答案 0 :(得分:3)
如果我们重写可能更容易理解发生了什么
@My_style("bold")
def greet():
return "Hello World"
没有装饰器语法糖:
def greet():
return "Hello World"
decorator = My_style("bold")
greet = decorator(greet)
您可以看到,第一步是创建可调用的装饰器(__init__
在那时被执行)。
然后我们称之为装饰器。这就是 __call__
被执行的时候,它应该返回新修饰的函数,我们将为其提供原始函数的名称 (greet
)。现在装饰器已经完成了它的工作,不会再参与任何事情了。
调用 greet
然后调用这个装饰函数(而不是装饰器的 __call__
方法!)。
因此,代码的更新版本,其中 __call__
创建并返回装饰函数:
class My_style:
#self.fn = fn
#fn= greet()
def __init__(self,s):
self.s = s
def __call__(self,fn):
def decorated():
if self.s == "upper":
return fn().upper()
elif self.s == "bold":
return "<b>" + fn() + "</b>"
return decorated
@My_style("bold")
def greet():
return "Hello World"
greet()
# '<b>Hello World</b>'
@My_style("upper")
def shout():
return "Hello World"
shout()
# 'HELLO WORLD'