私は 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
を持たない Session インスタンスではなく、キャッシャー オブジェクトであることです。pl
ただし、これを解決する方法が見つかりません。
私が考えたが使用できない解決策- 正しいコンテキストで評価されるように、デコレータ クラスが値の代わりに関数を返すようにすることを考えました (この記事のセクション 2.1 のように)self
が、それは不可能です。私のデコレーターはクラスとして実装され、組み込み __call__
メソッドを使用しているためです。次に、__call__メソッドが必要ないように、デコレーターにクラスを使用しないself.cache
ことを考えましたが、デコレーター呼び出し間で状態を保持する必要があるため (つまり、属性の内容を追跡するため)、それはできません。.
質問- グローバルcache
ディクショナリ変数を使用する以外に (試したことはありませんが、うまくいくと思います)、このデコレータを機能させる方法はありますか?
編集: この SO の質問は似ているようですDecorating python class methods, how do I pass the instance to the decorator?