我需要在实例级别应用memoization,所以我使用了以下装饰器:
from functools import partial, update_wrapper
class memoize(object):
def __init__(self, func):
self.func = func
update_wrapper(self, func)
def __get__(self, obj):
if obj is None:
return self.func
return partial(self, obj)
def __call__(self, *args, **kwargs):
obj = args[0]
try:
cache = obj.__cache__
except AttributeError:
cache = obj.__cache__ = {}
key = (self.func, args[1:], frozenset(kwargs.items()))
try:
res = cache[key]
except KeyError:
res = cache[key] = self.func(*args, **kwargs)
return res
适用时:
class A(object):
def __init__(self, parent):
self.parent = parent
def undecorated_method(self, pose, frame):
pass
@memoize
def decorated_method(self, pose, frame):
pass
我找到的唯一可以访问它的方法是A.__dict__["decorated_method"]
。尝试getattr(A, "decorated_method")
或getattr(A(5), "decorated_method")
或A.decorated_method
等都会失败:
TypeError: __get__() takes exactly 2 arguments (3 given)
真实代码的实际追溯是:
Traceback (most recent call last):
File "./regenerate_launch_files.py", line 145, in <module>
main()
File "./regenerate_launch_files.py", line 130, in main
verify_coeffs(method, past_image_keys)
File "./regenerate_launch_files.py", line 117, in verify_coeffs
if not (inspect.ismethod(getattr(evaluator, component))
TypeError: __get__() takes exactly 2 arguments (3 given)
调用未修饰的方法没有问题。
>>> getattr(A, "undecorated_method")
<unbound method __main__.A.undecorated_method>
(在Python 3中,“未修饰的方法”会提供<function __main__.A.undecorated_method>
,但getattr(A, "decorated_method")
仍然会失败并显示TypeError: __get__() takes 2 positional arguments but 3 were given
。)
可能导致什么?我怎样才能找到所给出的论点?我该如何调试和/或修复它?
答案 0 :(得分:0)
getattr
将以下参数传递给memoize
&#39; __get__
:
* `self`
* `None`
* `<class '__main__.A'>`
这就是导致错误的原因。解决它:
def __get__(self, instance, owner):
if instance is None:
return self.func
return partial(self, instance)