我一直很难真正了解Python的一些高级概念。我只是觉得我终于理解了装饰师并撞到了另一面墙。
据我了解,装饰者的核心事实是以下两件事完全相同:
@function_generator
def original_function:
...
和
original_function = function_generator(original_function)
也就是说正在做的是function_generator
被调用并传递original_function
,然后function_generator
回到另一个函数,然后给出原始函数的名称,所以当代码调用original_function
时,真正执行的是函数生成器返回的代码。
但后来我尝试了这个:
def decorator(passed_func, times):
"""the decorator"""
def replacement():
"""the replacement"""
for i in range(times):
passed_func()
return replacement
#@decorator
def print_name():
"""prints my name"""
print("My name is Benn")
iterate = int(input("How many times?"))
print_name = decorator(print_name, iterate)
print_name()
此代码工作正常,完全符合我的预期。但是当我取消注释@decorator
并注释掉print_name = decorator(print_name, iterate)
时,它会崩溃。
我运行此代码测试的原因是因为我看到了一个装饰器的高级示例,他们说我们必须将装饰器包装在另一个函数中以传入参数(如iterate
)。但是,在我看来,如果这是真的,那么@func2
仅仅是将func1=func2(func1)
打成谎言的句法糖。
以下哪项是正确的:
键入func1=func2(func1)
与@func2
的{{1}}并不完全相同,因为如果是def
,那么func1
是否有效然后func1=func2(func1,arg)
作为装饰者会工作;或
它们是相同的,即使从上面的例子看起来恰恰相反 - 如果是这样,为什么它看起来恰恰相反?
这就是我现在挂断的东西。为什么有这么多人说@func2
只是另一种写@decorator
的方法,当你在混合中添加一个参数时它不会那样工作?
答案 0 :(得分:0)
那是因为实际上你还是不太懂装饰师。如果你想将参数传递给装饰器,装饰器应该像这样嵌套,参数在入口级别,并且func在内层传递。
def decorator(times):
def wrapper(passed_func):
"""the wrapper"""
def replacement():
"""the replacement"""
for i in range(times):
passed_func()
return replacement
return wrapper
# @decorator(3)
def print_name():
"""prints my name"""
print("My name is Benn")
iterate = int(input("How many times?"))
print_name = decorator(iterate)(print_name)
print_name()
您可以取消注释装饰器并按照您的意愿进行尝试。
答案 1 :(得分:0)
您可以这样做的一种方法是创建一个装饰工厂:一个返回装饰器的函数。调用它的语法看起来像带有参数列表的装饰器。这是您的代码的修改版本:
def decorator_factory(times):
def decorator(passed_func):
"""the decorator"""
def replacement():
"""the replacement"""
for i in range(times):
passed_func()
return replacement
return decorator
iterates = int(input("How many times? "))
@decorator_factory(iterates)
def print_name():
"""prints my name"""
print("My name is Benn")
print_name()
<强>演示强>
How many times? 4
My name is Benn
My name is Benn
My name is Benn
My name is Benn
如果我们重写这段代码的最后一部分,可能有助于理解发生了什么:
dec = decorator_factory(iterates)
@dec
def print_name():
"""prints my name"""
print("My name is Benn")
所以decorator_factory(iterates)
返回dec
,然后dec
用于装饰print_name
。