Frage

Ich habe eine Basisklasse mit einer Eigenschaft, die (die get-Methode) I in der Unterklasse überschrieben werden soll. Mein erster Gedanke war so etwas wie:

class Foo(object):
    def _get_age(self):
        return 11

    age = property(_get_age)


class Bar(Foo):
    def _get_age(self):
        return 44

Das funktioniert nicht (Unterklasse bar.age zurück 11). Ich fand eine Lösung mit einem Lambda-Ausdruck, das funktioniert:

age = property(lambda self: self._get_age())

Das ist also die richtige Lösung für Eigenschaften mit und überschreiben sie in einer Unterklasse, oder gibt es andere bevorzugte Möglichkeiten, dies zu tun?

War es hilfreich?

Lösung

ich einfach lieber die property() auch wiederholen, wie Sie den @classmethod Dekorateur wiederholen, wenn eine Klasse Methode überschrieben.

Während dies sehr ausführlich scheint, zumindest für Python-Standards, können Sie feststellen:

1) für Nur-Lese-Eigenschaften kann property als Dekorateur verwendet werden:

class Foo(object):
    @property
    def age(self):
        return 11

class Bar(Foo):
    @property
    def age(self):
        return 44

2) in Python 2.6, Eigenschaften wurden ein Paar von Methoden setter und deleter, die verwendet werden können, um die allgemeinen Eigenschaften der Verknüpfung bereits für nur-Lese-diejenigen anwenden:

class C(object):
    @property
    def x(self):
        return self._x

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

Andere Tipps

Ich bin nicht einverstanden, dass die gewählte Antwort der ideale Weg ist für Überschreiben der Eigenschaft Methoden zu ermöglichen. Wenn Sie die Getter und Setter werden außer Kraft gesetzt erwarten, dann können Sie Lambda verwenden, um Zugriff auf Selbst zu schaffen, mit so etwas wie lambda self: self.<property func>.

Das funktioniert (zumindest) für Python-Versionen 2,4-3,6.

Wenn jemand einen Weg weiß dies zu tun, indem er als Dekorateur mit Eigentum statt als direkte Eigenschaft () -Aufruf, ich mag es hören!

Beispiel:

class Foo(object):
    def _get_meow(self):
        return self._meow + ' from a Foo'
    def _set_meow(self, value):
        self._meow = value
    meow = property(fget=lambda self: self._get_meow(),
                    fset=lambda self, value: self._set_meow(value))

Auf diese Weise kann eine Überschreibung leicht durchgeführt werden:

class Bar(Foo):
    def _get_meow(self):
        return super(Bar, self)._get_meow() + ', altered by a Bar'

, so dass:

>>> foo = Foo()
>>> bar = Bar()
>>> foo.meow, bar.meow = "meow", "meow"
>>> foo.meow
"meow from a Foo"
>>> bar.meow
"meow from a Foo, altered by a Bar"

Ich entdeckte diese auf aussenseiter im Spiel .

Eine andere Möglichkeit, es zu tun, ohne zusätzliche Klassen erstellen zu müssen. Ich habe eine Set-Methode zu zeigen, hinzugefügt, was Sie tun, wenn Sie nur eine der beiden außer Kraft setzen:

class Foo(object):
    def _get_age(self):
        return 11

    def _set_age(self, age):
        self._age = age

    age = property(_get_age, _set_age)


class Bar(Foo):
    def _get_age(self):
        return 44

    age = property(_get_age, Foo._set_age)

Das ist ein ziemlich konstruiertes Beispiel, aber man sollte die Idee.

Ja, das ist der Weg, es zu tun; die Eigenschaft Erklärung führt die Elternklasse Definition ausgeführt zu der Zeit, was bedeutet, es kann nur ‚sehen‘, die Versionen der Methoden, die auf der übergeordneten Klasse vorhanden sein. Also, wenn Sie eine oder mehr diese Methoden auf einem Kind Klasse neu definieren, müssen Sie neu deklarieren die Eigenschaft mit der Kind Klasse Version des Verfahrens (e).

Ich stimme mit Ihrer Lösung, die eine on-the-fly-Vorlage Methode scheint. diesem Artikel mit Ihrem Problem befasst und bietet genau Ihre Lösung.

So etwas wie dies funktionieren wird,

class HackedProperty(object):
    def __init__(self, f):
        self.f = f
    def __get__(self, inst, owner):    
        return getattr(inst, self.f.__name__)()

class Foo(object):
    def _get_age(self):
        return 11
    age = HackedProperty(_get_age)

class Bar(Foo):
    def _get_age(self):
        return 44

print Bar().age
print Foo().age

Wie bei @ mr-b 's aber mit Dekorateur.

class Foo(object):
    def _get_meow(self):
        return self._meow + ' from a Foo'
    def _set_meow(self, value):
        self._meow = value
    @property
    def meow(self):
        return self._get_meow()
    @meow.setter
    def meow(self, value):
        self._set_meow(value)

Auf diese Weise kann eine Überschreibung leicht durchgeführt werden:

class Bar(Foo):
    def _get_meow(self):
        return super(Bar, self)._get_meow() + ', altered by a Bar'

Ich lief in Probleme eine Eigenschaft in einer übergeordneten Klasse von einem Kind Klasse. Die folgende workround erstreckt sich eine Eigenschaft eines Elternteils, aber tut dies durch die _set_age Methode des Mutter direkt aufrufen. Faltig sollte immer richtig sein. Es ist ein wenig javathonic though.

import threading


class Foo(object):
    def __init__(self):
        self._age = 0

    def _get_age(self):
        return self._age

    def _set_age(self, age):
        self._age = age

    age = property(_get_age, _set_age)


class ThreadsafeFoo(Foo):

    def __init__(self):
        super(ThreadsafeFoo, self).__init__()
        self.__lock = threading.Lock()
        self.wrinkled = False

    def _get_age(self):
        with self.__lock:
             return super(ThreadsafeFoo, self).age

    def _set_age(self, value):
        with self.__lock:
            self.wrinkled = True if value > 40 else False
            super(ThreadsafeFoo, self)._set_age(value)

    age = property(_get_age, _set_age)
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top