实施例: 具有memoize装饰器的Fibonaci递归函数。调用函数助手时没有参数。如果函数助手被定义为接受参数x,那么我期望用一个参数调用函数。我想理解为什么语法是这样的?
def memoize(f):
memo = {}
def helper(x):
if x not in memo:
memo[x] = f(x)
return memo[x]
return helper
@memoize
def fib(n):
if n == 0:
return 0
elif n == 1:
return 1
else:
return fib(n-1) + fib(n-2)
print(fib(40))
答案 0 :(得分:2)
您可以使用参数调用帮助程序。装饰者是这个
的语法糖def fib(n):
if n == 0:
return 0
elif n == 1:
return 1
else:
return fib(n-1) + fib(n-2)
fib = memoize(fib)
因此,您的fib
函数不再是原始fib
- 函数。它实际上是helper
闭包,因为那是memoize
返回的 - 闭包。因此,当您致电fib(40)
时,您可以致电helper(40)
。 memoize
装饰器创建一个函数对象,它不会调用它,只返回它。
答案 1 :(得分:0)
我相信语法是这样的,所以它看起来尽可能简化。你在@
(一个接受一个参数的函数,并返回一个函数)之后放置一个装饰器对象,python用你定义的函数调用它。此
@memoize
def fib(n):
...
完全等同于以下内容,它不使用魔术装饰器语法:
def fib(n):
...
fib = memoize(fib)
如果你想让你的头旋转一点,可以考虑@
实际上可以跟一个函数调用 - 但是这个函数调用必须返回一个如上所述的装饰器!这是一个愚蠢的例子,它计算调用修饰函数的次数,但允许您设置起始值。 (这只是一个例子:它不是很有用,因为只有一个功能可以装饰等)。
def countcalls(start):
global _calls
_calls = start
def decorator(f):
def wrapper(x):
global _calls
_calls += 1
return f(x)
return wrapper
return decorator
@countcalls(3)
def say(s):
print(s)
say("hello")
# _calls is now 4
这里,countcalls(4)
定义并返回(不调用它)函数decorator
,它将包装装饰函数并返回包装器来代替我写的函数。