2017-06-02 3 views
2

Ich habe ein Objekt mit einem Haufen Getter und Setter auf sie. Ich möchte an dieses Objekt delegieren, einschließlich des Abholens und Festlegens. Ich möchte auch einige Setter in der delegierenden Klasse überschreiben können. Die Delegierung wie beschrieben here funktioniert für Getter aber nicht für Setter. Gibt es einen einfachen Weg dies zu tun, um alle Setter ausführlich zu duplizieren?Python @ Property Setter Delegation

Zum Beispiel im Anschluss an den zugrunde liegenden @a.setter nie getroffen:

class A: 
    _a = 'A.a' 
    _b = 'A.b' 

    @property 
    def a(self): 
    print('A.a.getter') 
    return self._a 

    @a.setter 
    def a(self, a): 
    print('A.a.setter') 
    self._a = a 

    @property 
    def b(self): 
    print('A.b.getter') 
    return self._b 

    @b.setter 
    def b(self, b): 
    print('A.b.setter') 
    self._b = b 

class B(object): 
    _A = None 

    def __init__(self, A): 
    self._A = A 

    @property 
    def b(self): 
    print('B.b.getter') 
    return self._A.b 

    @b.setter 
    def b(self, b): 
    print('B.b.setter') 
    self._A.b = b 

    def __getattr__(self, name): 
    return getattr(self._A, name) 

b = B(A()) 
print(b.a) 
b.a = 123 
b.b = 456 
+0

Sollte Ihr '__setattr__' nicht' setattr (self._A, name, value) 'sein, damit delegation funktioniert? – phd

+0

Nein, das funktioniert nicht. Der __setattr __() im Beispielcode ist eigentlich nur nichts Kesselplatte. Wenn Sie es entfernen, ist das Verhalten identisch. Ich hatte erwartet, dass ich die Logik verwenden würde, um auf den Setter dort zuzugreifen ... Ich habe ihn aus dem Beispielcode entfernt, um Verwirrung zu vermeiden. – spinkus

Antwort

2

nicht sicher, wie Sie __setattr__ verwenden, aber das funktioniert für mich:

class A(object): 
    _a = 'A.a' 

    @property 
    def a(self): 
    print('A.a.getter') 
    return self._a 

    @a.setter 
    def a(self, a): 
    print('A.a.setter') 
    self._a = a 

class B(object): 
    _A = None 

    def __init__(self, A): 
    self._A = A 
    self.b = 'B.b' 

    def __getattr__(self, name): 
    return getattr(self._A, name) 

    def __setattr__(self, name, value): 
    try: 
     super(B, self).__setattr__(name, value) 
    except AttributeError: 
     setattr(self._A, name, value) 

b = B(A()) 
print(b.a) 
b.a = 78 

Ausgang:

A.a.getter 
A.a 
A.a.setter 

Aktualisierung: In Python 2 müssen Sie new-style classes verwenden.

+0

Hit und Problem damit, dass ich Eigenschaften in "B" nicht überschreiben kann. Teil des Delegationsmandats ist, dass dies bei einigen Eigenschaften möglich ist. – spinkus

+0

@spinkus Richtig, ich dachte nur an den Anwendungsfall des Hinzufügens neuer Eigenschaften oder Methoden zu einem Objekt durch Delegierung. Wenn Sie dieses "übergeordnete" Verhalten haben wollen, müssen Sie nur die Reihenfolge in "B .__ setattr__" ändern, ich habe die Antwort mit dem Fix bearbeitet. – jdehesa