Question

J'ai une classe de base avec une propriété que (la méthode get) je veux écraser 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 (la sous-classe bar.age renvoie 11). J'ai trouvé une solution avec une expression lambda qui fonctionne:

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

C’est donc la bonne solution pour utiliser les propriétés et les écraser dans une sous-classe, ou existe-t-il d’autres moyens de procéder?

Était-ce utile?

La solution

Je préfère simplement répéter le property () et le décorateur @classmethod lors de la substitution d'une méthode de classe.

Bien que cela semble très bavard, du moins pour les normes Python, vous remarquerez peut-être:

1) pour les propriétés en lecture seule, la propriété peut être utilisée comme décorateur:

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

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

2) dans Python 2.6, les propriétés ont été enrichies d'une paire de méthodes setter et deleter pouvant être utilisés pour appliquer aux propriétés générales le raccourci déjà disponible pour ceux qui ne peuvent être qu’en lecture seule:

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

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

Autres conseils

Je ne pense pas que la réponse choisie soit le moyen idéal de remplacer les méthodes de propriété. Si vous vous attendez à ce que les getters et les setters soient remplacés, vous pouvez utiliser lambda pour fournir un accès à self, avec quelque chose comme lambda self: self. & Lt; property func > .

Ceci fonctionne (au moins) pour les versions de Python 2.4 à 3.6.

Si quelqu'un connaît un moyen de faire cela en utilisant une propriété en tant que décorateur plutôt qu'un appel direct à 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 substitution peut être facilement effectuée:

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

pour 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 cela sur geek en jeu .

Une autre façon de le faire, sans avoir à créer de classes supplémentaires. J'ai ajouté une méthode set pour montrer ce que vous faites si vous ne remplacez que 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 bel exemple artificiel, mais vous devriez en avoir l’idée.

Oui, c'est la façon de le faire. la déclaration de propriété est exécutée au moment de l'exécution de la définition de la classe parente, ce qui signifie qu'elle ne peut que "voir". les versions des méthodes qui existent sur la classe parente. Ainsi, lorsque vous redéfinissez une ou plusieurs de ces méthodes sur une classe enfant, vous devez re-déclarer la propriété en utilisant la version de la ou des méthodes de la classe enfant.

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

Quelque chose comme ça va marcher

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

Identique à @ mr-b mais avec un décorateur.

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)

De cette façon, une substitution peut être facilement effectuée:

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

J'ai rencontré des problèmes lors de la définition d'une propriété dans une classe parent à partir d'une classe enfant. Le workround suivant étend une propriété d'un parent, mais en appelant directement la méthode _set_age du parent. Ridée devrait toujours être correcte. C'est un peu javathonique cependant.

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)
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top