python - 从具有类作为装饰器的函数装饰器返回
问题描述
这是我的一段代码(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'
可能参数化调用需要它显式返回函数(在调用方法中)?
解决方案
如果我们重写,可能更容易理解发生了什么
@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'
推荐阅读
- excel - 如何在数组中输入最后一列以将文本转换为列?
- c# - 将具有结构数组的结构从 c# 传递到 c++
- python - Pandas LOC 选择值背后的逻辑
- javascript - 如何在jQuery中为变量添加最大值和最小值
- variadic-functions - CPython如何解析`*args`?
- flutter - 如何在标题下方制作带有图标的 AppBar?
- gmail - Sendgrid 模板:电子邮件正文隐藏在 gmail 中
- html-email - HTML 电子邮件模板在 Outlook 窗口中变得混乱
- android - 在 react-native 中运行 android 后台任务
- ruby-on-rails - 如何设置控制器参数的默认值?