2012-07-31 10 views
17

Ich habe eine Klasse mit einem dumpfen sich wiederholenden Muster auf ihren Funktionen und ich wollte dieses Muster in einen Dekorateur verwandeln. Aber die Sache ist, dass dieser Dekorator auf einige Attribute der aktuellen Instanz zugreifen muss, also wollte ich ihn zu einer Methode in dieser Klasse machen. Ich habe ein paar Probleme damit.Kann eine Methode ein Dekorator einer anderen Methode derselben Klasse sein?

Also, das ist ähnlich zu dem, was ich will:

class DullRepetitiveClass: 
    def __init__(self, nicevariable): 
     self.nicevariable = nicevariable 

    def mydecorator(self, myfunction): 
     def call(*args, **kwargs): 
      print "Hi! The value of nicevariable is %s"%(self.nicevariable,) 
      return myfunction(*args, **kwargs) 
     return call 

    @mydecorator   #Here, comment (1) below. 
    def somemethod(self, x): 
     return x + 1 

(1) Hier ist das Problem. Ich möchte die Methode DullRepetitiveClass.mydecorator verwenden, um die Methode somemethod zu dekorieren. Aber ich habe keine Ahnung, wie ich die Methode der aktuellen Instanz als Dekorateur verwenden soll.

Gibt es eine einfache Möglichkeit, dies zu tun?

EDIT: Ok, die Antwort ist ziemlich offensichtlich. Wie Sven es ausdrückt, transformiert der Dekorateur selbst die Methode. Die Methode selbst sollte alle Dinge in Bezug auf die Instanz behandeln:

def mydecorator(method): 
    def call(self, *args, **kwargs): 
     print "Hi! The value of nicevariable is %s"%(self.nicevariable,) 
     return method(self, *args, **kwargs) 
    return call 


class DullRepetitiveClass: 
    def __init__(self, nicevariable): 
     self.nicevariable = nicevariable 

    @mydecorator    
    def somemethod(self, x): 
     return x + 1 
+1

Bitte korrigieren Sie Ihre Einrückung. Beachten Sie auch, dass Ihr Code keine Klassenmethoden enthält. –

+0

Fragen Sie, wie Sie eine * andere * Instanz anders als 'self' an' mydecorator' übergeben, da sie 'somemethod' verziert? – kojiro

+0

Hoppla. Kopieren von Vim und Einfügen in den Browser kann manchmal ein Schmerz sein ... –

Antwort

11

Der Decorator erhält nur einen Parameter - die Funktion oder Methode, die es verziert. Es wird keine Instanz als self Parameter übergeben - im Moment der Dekorator aufgerufen wird, nicht einmal die Klasse wurde erstellt, geschweige denn eine Instanz der Klasse. Die Instanz wird als erstes Argument an die verzierte Funktion übergeben, daher sollten Sie self als ersten Parameter in die Parameterliste von call() aufnehmen.

Ich sehe nicht die Notwendigkeit, den Dekorator in den Klassenumfang aufzunehmen. Sie können dies tun, aber Sie können es auch im Modulbereich haben.

+0

Verdammt, es ist so offensichtlich. Der Decorator empfängt nur die Methode und gibt eine modifizierte Methode zurück. Die Methode ist der Typ, der sich mit der Instanz befassen muss ... verdammt. So offensichtlich. –

+0

Was ist, wenn dein Dekorateur Klassenmitglieder benutzen muss? Oder ist das nur eine schlechte Idee/Muster? – aaronlevin

+0

@weirdcanada: Da die Klasse zum Zeitpunkt des Aufrufs des Dekorators noch nicht erstellt wurde, können Sie nicht auf normale Weise auf die Elemente zugreifen. Sie können ein paar Hacks machen, um dies zu umgehen (Dinge wie "locals()" als Parameter an den Dekorateur übergeben), aber sie sind eher nicht offensichtlich, und ich kann mir keinen guten Grund vorstellen, dies zu tun. –

Verwandte Themen