Python 装饰器有和没有语法糖的区别?
Difference between Python decorator with and without syntactic sugar?
我正在尝试实现一个可记住任意函数的装饰器。看来我已经使用以下代码成功完成了:
def memoize(func):
cache = {}
def wrapper(*args, **kwargs):
acc = ""
for arg in args:
acc += str(arg)
if acc in cache:
return cache[acc]
else:
cache[acc] = func(*args, **kwargs)
return cache[acc]
return wrapper
@memoize
def fib(n):
if n == 0 or n == 1:
return 1
else:
return fib(n - 1) + fib(n - 2)
然后 fib(100)
returns 573147844013817084101
相当快。但是,如果我不使用语法糖:
def fib(n):
if n == 0 or n == 1:
return 1
else:
return fib(n - 1) + fib(n - 2)
memoized = memoize(fib)
print memoized(100)
函数挂起。调试它,看起来返回的包装器无法修改缓存。有人可以解释这种行为吗?据我所知,加糖和不加糖应该没什么区别。
您的递归调用没有记忆,因为您使用了新名称,而不是原始的fib
函数名称。每个 fib()
迭代都会回调 fib()
,但这将调用 原始的、未修饰的函数 .
将装饰器调用的 return 值改为 fib
:
def fib(n):
if n == 0 or n == 1:
return 1
else:
return fib(n - 1) + fib(n - 2)
fib = memoize(fib)
print fib(100)
或者,如果您必须使用 memoize
作为装饰器结果的名称,请 fib()
调用 memoized()
进行递归调用:
def fib(n):
if n == 0 or n == 1:
return 1
else:
return memoized(n - 1) + memoizzed(n - 2)
memoized = memoized(fib)
print memoized(100)
请记住,@decorator
语法分配给 相同的名称 ,而不是新名称。下面两个是等价的:
@memoize
def fib(n):
# ....
和
def fib(n):
# ....
fib = memoize(fib) # Same name!
除了名称 fib
永远不会首先绑定到原始函数。
我正在尝试实现一个可记住任意函数的装饰器。看来我已经使用以下代码成功完成了:
def memoize(func):
cache = {}
def wrapper(*args, **kwargs):
acc = ""
for arg in args:
acc += str(arg)
if acc in cache:
return cache[acc]
else:
cache[acc] = func(*args, **kwargs)
return cache[acc]
return wrapper
@memoize
def fib(n):
if n == 0 or n == 1:
return 1
else:
return fib(n - 1) + fib(n - 2)
然后 fib(100)
returns 573147844013817084101
相当快。但是,如果我不使用语法糖:
def fib(n):
if n == 0 or n == 1:
return 1
else:
return fib(n - 1) + fib(n - 2)
memoized = memoize(fib)
print memoized(100)
函数挂起。调试它,看起来返回的包装器无法修改缓存。有人可以解释这种行为吗?据我所知,加糖和不加糖应该没什么区别。
您的递归调用没有记忆,因为您使用了新名称,而不是原始的fib
函数名称。每个 fib()
迭代都会回调 fib()
,但这将调用 原始的、未修饰的函数 .
将装饰器调用的 return 值改为 fib
:
def fib(n):
if n == 0 or n == 1:
return 1
else:
return fib(n - 1) + fib(n - 2)
fib = memoize(fib)
print fib(100)
或者,如果您必须使用 memoize
作为装饰器结果的名称,请 fib()
调用 memoized()
进行递归调用:
def fib(n):
if n == 0 or n == 1:
return 1
else:
return memoized(n - 1) + memoizzed(n - 2)
memoized = memoized(fib)
print memoized(100)
请记住,@decorator
语法分配给 相同的名称 ,而不是新名称。下面两个是等价的:
@memoize
def fib(n):
# ....
和
def fib(n):
# ....
fib = memoize(fib) # Same name!
除了名称 fib
永远不会首先绑定到原始函数。