Я новичок в декораторах Python (ничего себе, отличная функция!), и мне нелегко заставить работать следующее, потому что аргумент self
получает вид смешения.
#this is the decorator
class cacher(object):
def __init__(self, f):
self.f = f
self.cache = {}
def __call__(self, *args):
fname = self.f.__name__
if (fname not in self.cache):
self.cache[fname] = self.f(self,*args)
else:
print "using cache"
return self.cache[fname]
class Session(p.Session):
def __init__(self, user, passw):
self.pl = p.Session(user, passw)
@cacher
def get_something(self):
print "get_something called with self = %s "% self
return self.pl.get_something()
s = Session(u,p)
s.get_something()
Когда я запускаю это, я получаю:
get_something called with self = <__main__.cacher object at 0x020870F0>
Traceback:
...
AttributeError: 'cacher' object has no attribute 'pl'
для строки, где я self.cache[fname] = self.f(self,*args)
Проблема. Очевидно, проблема заключается в том, что self
является объектом cacher вместо экземпляра сеанса, который действительно не имеет атрибута pl
. Однако я не могу найти, как это решить.
Решения, которые я рассмотрел, но не могу использовать - я думал о том, чтобы класс декоратора возвращал функцию вместо значения (как в разделе 2.1 этого article), так что self
оценивается в правильном контексте, но это невозможно, поскольку мой декоратор реализован как класс и использует встроенный __call__
. Затем я решил не использовать класс для моего декоратора, так что мне не нужен метод __call__, но я не могу этого сделать, потому что мне нужно поддерживать состояние между вызовами декоратора (т.е. Для отслеживания того, что находится в self.cache
).
Вопрос. Итак, помимо использования глобальной переменной словаря cache
(которую я не пробовал, но предполагаю, что она будет работать), есть ли другой способ заставить этот декоратор работать?
Изменить: этот вопрос SO похож на Украшая методы класса python, как передать экземпляр в декоратор?