Проблема в том, что вы определили свой собственный вызываемый класс, а затем попытались использовать его как метод. Когда вы используете функцию в качестве атрибута, доступ к функции в качестве атрибута вызывает ее метод __get__
для возврата чего-то другого, кроме самой функции - связанного метода. Когда у вас есть свой собственный класс без определения __get__
, он просто возвращает ваш экземпляр без неявной передачи self
.
Дескрипторы объяснены некоторые на http://docs.python.org/reference/datamodel.html#descriptors, если вы не знакомы с ними. Методы __get__
, __set__
и __delete__
изменяют способ взаимодействия с вашим объектом в качестве атрибута.
Вы можете реализовать memoize
как функцию и использовать встроенную магию __get__
, которая уже имеет функции
import functools
def memoize(f):
@functools.wraps(f)
def memoized(*args, _cache={}):
# This abuses the normally-unwanted behaviour of mutable default arguments.
if args not in _cache:
_cache[args] = f(*args)
return _cache[args]
return memoized
или изменив свой класс в соответствии с
import functools
class Memoize(object): #inherit object
def __init__(self, function):
self.function = function
self.memoized = {}
def __call__(self, *args): #don't accept kwargs you don't want.
# I removed "hash = args" because it shadowed a builtin function and
# because it was untrue--it wasn't a hash, it was something you intended for
# Python to hash for you.
try:
return self.memoized[args]
except KeyError:
self.memoized[args] = self.function(*args)
return self.memoized[args]
def __get__(self, obj, type):
if obj is None: #We looked up on the class
return self
return functools.partial(self, obj)
Обратите внимание, что оба из этих дросселей, если какой-либо из аргументов, которые вы передаете, являются изменчивыми (ну, технически непостижимыми). Это может подойти для вашего случая, но вы также можете иметь дело со случаем, когда args
не подлежит отмене.