2016-06-30 2 views
0

мне нужно мемоизации для применения на уровне экземпляра, поэтому я использовал следующий декоратор:GetAttr на украшенной метод генерирует TypeError

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

getattr проезжал следующие аргументы memoize «s __get__:

* `self` 
* `None` 
* `<class '__main__.A'>` 

Это было то, что вызывает ошибку. Чтобы исправить это:

def __get__(self, instance, owner): 
    if instance is None: 
     return self.func 
    return partial(self, instance)