Je change certaines de mes classes d'une utilisation extensive des getters et setters à une utilisation plus pythonique des propriétés.
Mais maintenant, je suis bloqué parce que certains de mes getters ou setters précédents appellent la méthode correspondante de la classe de base, puis effectuent autre chose. Mais comment cela peut-il être accompli avec des propriétés? Comment appeler le getter ou le setter de propriété dans la classe parent?
Bien sûr, le simple fait d'appeler l'attribut lui-même donne une récursion infinie.
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
Vous pourriez penser que vous pourriez appeler la fonction de classe de base qui est appelée par la propriété:
class FooBar(Foo):
@property
def bar(self):
# return the same value
# as in the base class
return Foo.bar(self)
Bien que ce soit la chose la plus évidente à essayer, je pense - cela ne fonctionne pas parce que la barre est une propriété, pas un appelable.
Mais une propriété n'est qu'un objet, avec une méthode getter pour trouver l'attribut correspondant:
class FooBar(Foo):
@property
def bar(self):
# return the same value
# as in the base class
return Foo.bar.fget(self)
Super devrait faire l'affaire:
return super().bar
Dans Python 2.x, vous devez utiliser la syntaxe la plus verbeuse:
return super(FooBar, self).bar
Il existe une alternative utilisant super
qui ne nécessite pas de référencer explicitement le nom de la classe de base.
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
Comme d'autres l'ont déjà répondu, c'est:
super(B, self).prop
Ou en Python 3:
super().prop
Cela renvoie la valeur renvoyée par le getter de la propriété, pas le getter lui-même mais il suffit d'étendre le getter.
La meilleure recommandation que j'ai vue jusqu'à présent est la suivante:
A.prop.fset(self, value)
Je crois que celui-ci est meilleur:
super(B, self.__class__).prop.fset(self, value)
Dans cet exemple, les deux options sont équivalentes mais l'utilisation de super a l'avantage d'être indépendante des classes de base de B
. Si B
devait hériter d'une classe C
étendant également la propriété, vous n'auriez pas à mettre à jour le code de B
.
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)
Sauf si votre propriété n'a pas de setter, vous devez définir à la fois le setter et le getter dans B
même si vous ne changez que le comportement de l'un d'eux.
essayer
@property
def bar:
return super(FooBar, self).bar
Bien que je ne sais pas si python prend en charge l'appel de la propriété de classe de base. Une propriété est en fait un objet appelable qui est configuré avec la fonction spécifiée, puis remplace ce nom dans la classe. Cela pourrait signifie facilement qu'il n'y a pas de super fonction disponible.
Cependant, vous pouvez toujours changer de syntaxe pour utiliser la fonction property ():
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