60 votes

python propriétés et à l'héritage

J'ai une classe de base avec une propriété qui (méthode get) je veux le remplacer dans la sous-classe. Ma première pensée a été quelque chose comme:

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

    age = property(_get_age)


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

Cela ne fonctionne pas (sous-classe de la barre.l'âge renvoie 11). J'ai trouvé une solution avec une expression lambda qui fonctionne:

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

Donc, est-ce la bonne solution pour utiliser les propriétés et les écraser dans une sous-classe, ou il y en a d'autres moyens privilégiés pour ce faire?

69voto

piro Points 4848

Je préfère tout simplement de répéter l' property() ainsi que vous allez répéter l' @classmethod décorateur lors du remplacement d'une méthode de classe.

Bien que cela semble très prolixe, au moins pour Python normes, on peut noter:

1) pour les propriétés en lecture seulement, property peut être utilisé comme un décorateur:

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

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

2) dans la version 2.6 de Python, des propriétés a augmenté une paire de méthodes d' setter et deleter qui peut être utilisé pour appliquer des propriétés générales le raccourci déjà disponibles en lecture seule:

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

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

Il est très facile de créer les mêmes décorateurs pour être utilisé avec les précédentes version de Python:

class setter(object):
    def __init__(self, prop):
        self.prop = prop
    def __call__(self, setter):
        return property(
            fget=self.prop.fget,
            fset=setter,
            fdel=self.prop.fdel,
            doc=self.prop.__doc__)

class C(object):
    def __init__(self):
        self._age = None

    @property
    def age(self): 
        """My age"""
        return self._age

    @setter(age)
    def age(self, n):
        self._age = n

19voto

Brian Visel Points 473

Je ne suis pas d'accord que la réponse choisie est le moyen idéal pour permettre la substitution de la propriété méthodes. Si vous vous attendez à les getters et setters pour être remplacé, vous pouvez utiliser lambda pour fournir l'accès à soi-même, avec quelque chose comme lambda self: self.<property func>.

Cela fonctionne (au moins) pour les versions de Python 2.4 à 3.4.

Si quelqu'un connaît un moyen de le faire avec l'aide de la propriété en tant que décorateur au lieu de directement de la propriété (), j'aimerais l'entendre!

Exemple:

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))

De cette façon, une dérogation peut être facilement réalisée:

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

de sorte que:

>>> 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"

J'ai découvert ce sur geek à jouer.

12voto

Kamil Kisiel Points 7298

Une autre façon de le faire, sans avoir à créer de toutes classes supplémentaires. J'ai ajouté une méthode de jeu pour montrer ce que vous faites si vous ne vous remplacer l'un des deux:

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)

C'est un joli exemple artificiel, mais vous devriez obtenir l'idée.

7voto

James Bennett Points 6318

Oui, c'est la façon de le faire; la déclaration de la propriété s'exécute à la fois le parent de la classe de définition est exécutée, ce qui signifie qu'il ne peut "voir" les versions des méthodes qui existent sur la classe parent. Ainsi, lorsque vous redéfinissez un ou plusieurs de ces méthodes sur un enfant de la classe, vous avez besoin de re-déclarer la propriété à l'aide de la classe enfant "version" de la méthode(s).

2voto

Federico A. Ramponi Points 23106

Je suis d'accord avec votre solution, qui semble à la volée modèle de méthode. Cet article traite votre problème et fournit exactement votre solution.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X