2010-09-15 9 views
6

Ich habe eine Klasse namens Cell:Einfache Methode zum Überschreiben von Standardmethoden in benutzerdefinierten Python-Klassen?

class Cell: 

    def __init__(self, value, color, size): 
     self._value = value 
     self._color = color 
     self._size = size 

    # and other methods... 

Cell._value speichert eine Zeichenfolge, Integer usw. (was auch immer ich dieses Objekt für verwende). Ich möchte alle Standardmethoden, die normalerweise den „Wert“ eines Objekts verwenden würde <Cell object>._value zu verwenden, so dass ich tun kann:

>>> c1 = Cell(7, "blue", (5,10)) 
>>> c2 = Cell(8, "red", (10, 12)) 
>>> print c1 + c2 
15 

>>> c3 = Cell(["ab", "cd"], "yellow", (50, 50)) 
>>> print len(c3), c3 
2 ['ab', 'cd'] 

# etc. 

Ich konnte alle Standardmethoden außer Kraft setzen:

class Cell: 

    def __init__(self, value, color, size): 
     # ... 

    def __repr__(self): 
     return repr(self._value) 

    def __str__(self): 
     return str(self._value) 

    def __getitem__(self, key): 
     return self._value[key] 

    def __len__(self): 
     return len(self._value) 

    # etc. 

... Aber gibt es einen leichteren Weg?

+1

Warum kann eine Ganzzahl, 'self._value', durch einen Schlüssel indiziert werden? Und hast du jemals versucht, die Länge einer ganzen Zahl zu nehmen? Auch sollte dies wahrscheinlich nicht cocmmunity wiki sein: niemand bekommt Punkte dafür, auf diese Weise zu antworten, und wir lieben uns einige Punkte hier bei SO. – aaronasterling

+2

-1: Dies sollte kein Wiki sein. –

+0

@AaronMcSmooth 'self._value' könnte jeden Datentyp enthalten, so dass ich alle möglichen Methoden verfügbar haben möchte. –

Antwort

11

Wenn ich Sie richtig verstehe, suchen Sie nach einer einfachen Möglichkeit, die Methode eines Objekts an eine Eigenschaft dieses Objekts zu delegieren?

Sie können einige der Eintönigkeit vermeiden, indem sie einen Dekorateur definieren:

def delegate(method, prop): 
    def decorate(cls): 
     setattr(cls, method, 
      lambda self, *args, **kwargs: 
       getattr(getattr(self, prop), method)(*args, **kwargs)) 
     return cls 
    return decorate 

Sie können dann für jede Methode der Dekorateur anwenden Sie delegiert werden sollen:

@delegate('__len__', '_content') 
@delegate('__getitem__', '_content') 
class MyList(object): 
    def __init__(self, content): 
     self._content = content 

spam = MyList([1,2,3,4,5]) 

len(spam) # prints "5" 

spam[0] # prints "1" 

Sie wahrscheinlich es weiter vereinfachen könnte durch Ändern des Dekorators, um mehrere Methodennamen als Argument zu verwenden.

Wenn Sie möchten, dass Ihre Klasse als vollständiger Wrapper fungiert, könnten Sie wahrscheinlich die Methode __getattr__ der Klasse überschreiben, um das umgebrochene Objekt vor dem Fehlschlagen zu überprüfen. Dies würde das Verhalten von Unterklassen ohne tatsächliche Vererbung emulieren.

+0

Ich denke, das Überschreiben von '__getattr__' ist näher an dem, was ich suche, aber ich sehe den Wert in der Decorator-Option auch. Jetzt muss ich nur noch den Unterschied zwischen "__getattr__" und "__getattribute__" verstehen: http://docs.python.org/reference/datamodel.html#object.__getattribute__ –

0

Sie müssen die Methode __add__ überladen, um das gewünschte Verhalten c1 + c2 zu erhalten.

Siehe here für Informationen darüber, was sie alle sind.

Verwandte Themen