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())
Donc, est-ce la bonne solution pour utiliser des propriétés et les écraser dans une sous-classe, ou y a-t-il d'autres façons préférées de le faire?
Je préfère simplement répéter le property()
ainsi que le décorateur @classmethod
lors du remplacement d'une méthode de classe.
Bien que cela semble très bavard, du moins pour les standards Python, vous remarquerez peut-être:
1) pour les propriétés en lecture seule, property
peut être utilisé 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, properties a développé une paire de méthodessetter
et deleter
qui peuvent être utilisées pour appliquer aux propriétés générales le raccourci déjà disponible pour celles en lecture seule:
class C(object):
@property
def x(self):
return self._x
@x.setter
def x(self, value):
self._x = value
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)
Ceci est un bel exemple artificiel, mais vous devriez avoir l’idée.
Je ne pense pas que la réponse choisie soit le moyen idéal de permettre de remplacer les méthodes de propriété. Si vous vous attendez à ce que les accesseurs et les setters soient remplacés, vous pouvez utiliser lambda pour fournir un 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.6.
Si quelqu'un connaît un moyen de le faire en utilisant propriété en tant que décorateur au lieu d'appeler directement 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 .
Oui, c'est la façon de le faire. la déclaration de propriété s'exécute au moment de l'exécution de la définition de la classe parente, ce qui signifie qu'elle ne peut "voir" que les versions des méthodes existant dans 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é à l'aide de la version de la ou des méthodes de la classe enfant.
Je suis d'accord avec votre solution, qui semble une méthode de modèle à la volée. Cet article traite de votre problème et fournit exactement votre solution.
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'
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
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)
class Foo:
# Template method
@property
def age(self):
return self.dothis()
# Hook method of TM is accessor method of property at here
def dothis(self):
return 11
class Bar(Foo):
def dothis(self):
return 44
Identique à Nizam Mohamed, juste pour mentionner que guide de style 2.13.4 en utilisant à la fois la méthode template et la propriété