我正在尝试为 memoize 编写 python 装饰器。 我有几个问题。
- @memoize 如何转化为 memoize 类的调用函数?
- 为什么 init 需要参数。
- 缓存存储在哪里?它与每个函数相关联还是一个全局变量?即如果我使用@memoize 是否会有两个缓存对象 多种功能。
..
class memoize:
def __init__(self):
self.cache = {}
def __call__(self, function):
def wrapper(*args, **kwargs):
key = str(function.__name__) + str(args) + str(kwargs)
if key in cache:
return cache[key]
else:
value = function(*args, **kwargs)
cache[key] = value
return value
return wrapper
@memoize
def fib(n):
if n in (0, 1):
return 1
else:
return fib(n-1) + fib(n-2)
for i in range(0, 10):
print(fib(i))
我遇到了编译错误。
Traceback (most recent call last):
File "memoize.py", line 17, in <module>
@memoize
TypeError: __init__() takes exactly 1 argument (2 given)
最佳答案
- 你应该记住
@decorator
只是func = decorator(func)
的语法糖。所以这里有一个区别:
(1)
@decorator
def func():
...
与
相同func = decorator(func) # Just call of __init__
func(...) # Call of decorator.__call__
但是 (2)
@decorator(some_param)
def func():
...
类似于
# Call of __init__ plus call of __call__
func = decorator(some_param)(func)
# Call of closure returned by decorator.__call__
func(...)
您已经为 (2) 语法实现了装饰器接受参数,但在使用它们时不要像示例 (1) 那样提供它们。这就是为什么
__init__
提示,它接收func
作为第二个参数。你应该在
wrapper
闭包中编写self.cache
,这样wrapper
就会引用相应的装饰器
对象。只写cache
会导致全局变量搜索,因此会失败。
UPD:我将您的代码更改为方法 (1):
class memoize:
def __init__(self, function):
self.cache = {}
self.function = function
def __call__(self, *args, **kwargs):
key = str(args) + str(kwargs)
if key in self.cache:
return self.cache[key]
value = self.function(*args, **kwargs)
self.cache[key] = value
return value
@memoize
def fib(n):
if n in (0, 1):
return 1
else:
return fib(n-1) + fib(n-2)
for i in range(0, 10):
print(fib(i))
print(fib.cache)
关于python - 我如何编写用于缓存的python装饰器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28145601/