Wie eine Eigenschaft der Basisklasse aufrufen, wenn diese Eigenschaft in der abgeleiteten Klasse überschrieben wird?

StackOverflow https://stackoverflow.com/questions/1021464

Frage

Ich bin einige Klassen von mir aus einer umfangreichen Verwendung von Getter und Setter zu einer pythonic Verwendung von Eigenschaften zu verändern.

Aber jetzt bin ich stecken, weil einige meiner früheren Getter oder Setter nennen würde die entsprechende Methode der Basisklasse, und dann etwas anderes ausführen. Aber wie kann dies mit Eigenschaften erreicht werden? Wie die Eigenschaft Getter oder Setter in der übergeordneten Klasse nennen?

Natürlich ruft nur das Attribut selbst gibt unendliche Rekursion.

class Foo(object):

    @property
    def bar(self):
        return 5

    @bar.setter
    def bar(self, a):
        print a

class FooBar(Foo):

    @property
    def bar(self):
        # return the same value
        # as in the base class
        return self.bar # --> recursion!

    @bar.setter
    def bar(self, c):
        # perform the same action
        # as in the base class
        self.bar = c    # --> recursion!
        # then do something else
        print 'something else'

fb = FooBar()
fb.bar = 7
War es hilfreich?

Lösung

Man könnte denken, Sie die Basisklasse Funktion aufrufen kann, die durch Eigenschaft genannt wird:

class FooBar(Foo):

    @property
    def bar(self):
        # return the same value
        # as in the base class
        return Foo.bar(self)

Obwohl dies das Selbstverständlichste zu versuchen Ich denke, -. es funktioniert nicht, weil bar eine Eigenschaft ist, kein aufrufbar

Aber eine Eigenschaft ist nur ein Objekt, mit einer Getter-Methode das entsprechende Attribut zu finden:

class FooBar(Foo):

    @property
    def bar(self):
        # return the same value
        # as in the base class
        return Foo.bar.fget(self)

Andere Tipps

super sollte den Trick tun:

return super().bar

In Python 2.x müssen Sie die ausführlichere Syntax:

return super(FooBar, self).bar

Es gibt eine Alternative mit super, die nicht explizit benötigt, um die Basisklasse Namen zu verweisen.

Basisklasse A:

class A(object):
    def __init__(self):
        self._prop = None

    @property
    def prop(self):
        return self._prop

    @prop.setter
    def prop(self, value):
        self._prop = value

class B(A):
    # we want to extend prop here
    pass

In B, die Eigenschaft Getter der Elternklasse A den Zugriff auf:

Wie andere haben bereits beantwortet, es ist:

super(B, self).prop

oder in Python 3:

super().prop

Dies gibt den Wert vom Getter der Eigenschaft zurückgegeben, nicht der Getter selbst, sondern es ist ausreichend, um den Getter zu verlängern.

In B, die Eigenschaft Setter der Elternklasse A den Zugriff auf:

Die beste Empfehlung, die ich bisher gesehen habe, ist die folgende:

A.prop.fset(self, value)

Ich glaube, das ist besser:

super(B, self.__class__).prop.fset(self, value)

In diesem Beispiel sind beide Optionen gleichwertig, aber Super haben den Vorteil, von den Basisklassen von B unabhängig zu sein. Wenn B von einer C Klasse erben waren auch die Eigenschaft erstreckt, würden Sie nicht müssen B den Code aktualisieren.

Vollständiger Code B A Eigentum erstreckt:

class B(A):
    @property
    def prop(self):
        value = super(B, self).prop
        # do something with / modify value here
        return value

    @prop.setter
    def prop(self, value):
        # do something with / modify value here
        super(B, self.__class__).prop.fset(self, value)

Eine Warnung:

Es sei denn, Ihr Eigentum keinen Setter haben, müssen Sie sowohl die Setter und Getter in B definieren, auch wenn Sie nur das Verhalten einer von ihnen ändern.

Versuch

@property
def bar:
    return super(FooBar, self).bar

Obwohl ich nicht sicher bin, ob Python unterstützt die Basisklasse Eigenschaft aufrufen. Eine Eigenschaft ist tatsächlich ein aufrufbare Objekt, das mit der Funktion oben angegeben gesetzt und ersetzt dann diesen Namen in der Klasse. Dies könnte leicht dazu führen, dass es keine Super-Funktion zur Verfügung.

Sie können immer schalten Sie Ihre Syntax obwohl die Eigenschaft () Funktion zu verwenden:

class Foo(object):

    def _getbar(self):
        return 5

    def _setbar(self, a):
        print a

    bar = property(_getbar, _setbar)

class FooBar(Foo):

    def _getbar(self):
        # return the same value
        # as in the base class
        return super(FooBar, self)._getbar()

    def bar(self, c):
        super(FooBar, self)._setbar(c)
        print "Something else"

    bar = property(_getbar, _setbar)

fb = FooBar()
fb.bar = 7
    class Base(object):
      def method(self):
        print "Base method was called"

    class Derived(Base):
      def method(self):
        super(Derived,self).method()
        print "Derived method was called"

    d = Derived()
    d.method()

(das ist, wenn ich etwas von Ihrer Erklärung fehle)

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top