2016-07-11 11 views
3

In meiner Codeklasse A hat eine Eigenschaft, aber Klasse B erbt es nicht. Unterstützt Vererbung? Oder ist es meine Schuld?Unterstützen Eigenschaften Vererbung?

class A(object): 

    def __init__(self): 
     self._x = 100 

    @property 
    def x(self): 
     return self._x 

    @x.setter 
    def x(self, v): 
     self._x = v 


class B(A): 

    @x.setter 
    def x(self, v): 
     self._x = v 

Die Fehlermeldung lautet wie folgt:

Traceback (most recent call last): 
    File "test.py", line 9, in <module> 
    class B(A): 
    File "test.py", line 10, in B 
    @x.setter 
NameError: name 'x' is not defined 
+2

Es sollte "@ A.x.setter" sein. 'x' steht hier unter dem Namensraum' A'. –

+0

Sie können eine Eigenschaft erben, aber Sie können sie nicht unabhängig ändern. Wenn Sie 'x' erben und einen Setter hinzufügen, wird es auch im Original enthalten sein. Sie können die Eigenschaft als 'x' definieren, um eine unabhängige Version zu erhalten. –

+0

Also ist 'x' im Elternteil schreibgeschützt, aber im Kind schreibgeschützt? – jonrsharpe

Antwort

2

Es weiß nur nicht, wo x von bekommen. Sie können dies tun, anstatt:

class A(object): 
    def __init__(self): 
     self._x = 100 

    @property 
    def x(self): 
     return self._x 

class B(A): 
    @A.x.setter 
    def x(self, v): 
     self._x = v 
+1

* "Wenn kein Setter vorhanden ist. A(). X = 1 überschreibt einfach die Eigenschaft" * - was? Versuchen Sie das in Python 2.x? Ohne einen Setter ist eine Eigenschaft schreibgeschützt, also gibt 'AttributError: Attribut kann nicht gesetzt werden' – jonrsharpe

+0

@jonrsharpe, Sie haben Recht. Ich habe A in eine neue Stilklasse geändert, jetzt ist es für python2 und python3 dasselbe –

3

Die NameError ist, weil x nicht im globalen Bereich ist; Es ist innerhalb des Klassen-Namensraums von A definiert, Sie müssen also explizit darauf zugreifen, indem Sie A.x verwenden. Dies ist ein ziemlich häufiger Fehler, siehe z.B. python subclass access to class variable of parent.

Mit Eigenschaften kann es jedoch etwas komplexer werden. Wenn Sie einen neuen Setter in B hinzufügen, dann gibt es kein Problem mit A.x.setter wie in Dean's answer gezeigt. Wenn Sie jedoch einen vorhandenen Setter überschreiben, ändern Sie auch das Verhalten von A. Ich bezweifle, dass dies das Verhalten ist, das du willst.

Stattdessen müssen Sie in diesem Fall eine neue Eigenschaft in der Unterklasse mit dem Getter A und einem neuen Setter erstellen. Ich denke, dass dies der einfachste Weg ist es, dass bei minimaler Wiederholung zu erreichen: die Verwendung von property ohne @ syntaktischen Zucker

class B(A): 

    x = property(A.x.__get__) # new property with same getter 

    @x.setter # new setter on new property 
    def x(self, v): 
     ... 

Hinweis, wie ich verwende es nicht eine neue Methode zu dekorieren. Wenn Sie auf A 's Setter von B Setter zugreifen möchten, können Sie dies mit super().x.__set__(whatever) tun.