2016-10-25 1 views
0

Hier meine Implementierung von memoize ist:Memoize für Klassen, deren init hat super() Initialisierung

Katze test.py

def _memoize(obj): 
    cache = obj.cache = {} 

    @functools.wraps(obj) 
    def memoizer(*args, **kwargs): 
     key = str(args) + str(kwargs) 
     if key not in cache: 
      cache[key] = obj(*args, **kwargs) 
     return cache[key] 
    return memoizer 

@_memoize 
class Test(object): 
    def __init__(self, arg1): 
     super(Test, self).__init__() 
     self.arg = arg1 
     print "init executed for " + arg1 

    def authenticate(self): 
     print self.arg 

t1 = Test('a') 

wenn ich dies laufe ich folgende Fehlermeldung erhalten:

python $ test.py

Traceback (most recent call last): 
    File "test.py", line 23, in <module> 
    t1 = Test('a') 
    File "test.py", line 9, in memoizer 
    cache[key] = obj(*args, **kwargs) 
    File "test.py", line 16, in __init__ 
    super(Test, self).__init__() 
TypeError: super() argument 1 must be type, not function 

Können Sie bitte vorschlagen, wie Sie diesen Fehler beheben?

+0

Also wollen Sie immer 'Test (x) ist Test (y)' wahr sein, wenn 'x == y' (oder zumindest, wenn 'hash (x) == hash (y)')? – chepner

Antwort

0

functools.wraps ist eine Annehmlichkeit für einen Funktionswrapper, und die Verwendung des Dekorators ist like wrapping Test in that function call;

Test = _memoize(Test) 

So, Test ist nicht mehr eine Klasse, es ist eine Funktion, und wie der Fehler zeigt super will kein funtion.

Ich verstehe nicht Ihre Absicht genug, eine Alternative vorzuschlagen.

1

Innerhalb Ihrer Memoizer-Funktion müssen Sie einen neuen Typ erstellen; Sie erstellen und geben eine Funktion zurück, und damit verwandeln Sie Ihre Klasse in eine Funktion. Ein einfacherer Weg, um das zu erreichen, was Sie tun möchten, wäre __new__ zu überschreiben, mit dem Sie Aufrufe an den Konstruktor abfangen können, bevor das Objekt zugewiesen wird. Sie könnten das tun (vereinfacht, aber Sie könnten Ihre Multi-Arg-Behandlung replizieren) auch):

class Test(object): 
    def __init__(self, arg): 
     self.x = arg 

    _cache = {} 
    def __new__(cls, arg): 
     if arg not in _cache: 
      _cache[arg] = cls(arg) 
     return _cache[arg] 

Wenn Sie etwas mehr Dekorateur-Stil wollen, können Sie bei __metaclass__ aussehen, die Sie eine ähnliche Sache in einer Art und Weise zu tun, erlaubt es, die sich über Klassen ohne Vererbung leichter gemeinsam genutzt werden.

Verwandte Themen