【发布时间】:2017-10-07 13:15:14
【问题描述】:
我一直难以真正理解 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) 输入谎言的语法糖。
那么下列哪项是正确的:
在
def上键入func1=func2(func1)与@func2的func1并不完全相同,因为如果是这样,那么如果func1=func2(func1,arg)有效,那么@func2作为装饰器就可以了;或它们是相同的,尽管从上面的示例中看起来完全相反——如果是这样,为什么看起来相反?
这就是我现在所关注的。为什么这么多人说@decorator 只不过是写func1=decorator(func1) 的另一种方式,而当您在其中添加参数时它不会那样工作?
【问题讨论】:
-
我不知道你是如何得出你的结论的。
@bondef a():与a = b(a)相同并不意味着a = b(a, c)也可以使用该语法;您认为times来自@decorator表单中的哪里?也许你应该看看例如stackoverflow.com/q/5929107/3001761 了解如何创建带参数的装饰器。 -
什么叫“崩溃”?
-
提示:装饰器采用 single 参数:要装饰的函数。但是你的装饰器要求 两个 args。那么它会从哪里得到
timesarg 呢? -
@Kanak 当他们使用装饰器表单时,它会抱怨没有提供所需的第二个位置参数。