首先,为了找到两个数字的“lcm”,我创建了一个函数lcm(a, b)。然后我想到也找到“hcf”,所以我做了一个装饰器 decor 并在其中定义了一个函数 hcf(a, b) 。然后我通过键入函数名称返回了这个函数,我没有用括号括起来,但它仍然有效。即使我没有使用括号,我也不明白为什么这个函数可以工作。
def decor(lcm_arg): # just to practice decorators
def hcf(a, b):
if a > b:
a, b = b, a
while True:
if b % a == 0:
print("hcf is", a)
break
else:
a, b = b % a, a
return lcm_arg(a, b)
return hcf # how hcf function is working without using brackets
@decor
def lcm(a, b):
if a > b:
a, b = b, a
for x in range(b, a*b+1, b):
if x % a == 0:
print("lcm is", x)
break
lcm(2, 4)
输出:
hcf is 2
lcm is 4
请您参考如下方法:
我觉得你不懂装饰器。让我们举一个最小的例子。
def my_decorator(some_function):
def new_function(*args, **kwargs):
'announces the result of some_function, returns None'
result = some_function(*args, **kwargs)
print('{} produced {}'.format(some_function.__name__, result))
return new_function # NO FUNCTION CALL HERE!
@my_decorator
def my_function(a, b):
return a + b
my_function(1, 2) # will print "my_function produced 3"
我们有一个简单的函数my_function,它返回它的两个参数的总和,还有一个装饰器,它只打印出它装饰的任何函数的结果。
注意
@my_decorator
def my_function(a, b):
return a + b
相当于
def my_function(a, b):
return a + b
my_function = my_decorator(my_function)
因为 my_decorator 接受一个函数作为参数(这里我们给它 my_function)并返回一个新函数 new_function(不调用它!),我们有效地覆盖了 my_function,因为我们将名称重新分配给 my_decorator 返回的任何内容。
在行动中:
>>> my_function(1, 2)
my_function produced 3
请注意,在调用函数的示例中的每一点,它都会使用括号语法。以下是我发布的第一段代码中发生的所有函数调用,按顺序排列:
my_decorator(my_function)被调用,返回值被重新分配给名称my_function。这要么通过@语法发生,要么在等效代码片段中更明确地发生。my_function(1, 2)被调用。此时,my_function就是装饰器返回的new_function。大脑将其解析为new_function(1, 2)。- 在
new_function的主体内,我们给my_decorator的参数被调用 (result = some_function(*args, **kwargs)) 这恰好是my_function在步骤 1 中发生的重新分配之前的值。 print被调用。
如果你想了解 new_function 是如何保持 some_function 尽管 my_decorator 已经从它的调用返回,我建议查看主题自由变量和闭包。
