otra - poo python 3
¿Cómo llamar a una propiedad de la clase base si esta propiedad se sobrescribe en la clase derivada? (5)
Existe una alternativa que usa super
que no requiere referencia explícita del nombre de la clase base.
Clase base A:
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
En B, accediendo al captador de propiedad de la clase padre A:
Como otros ya han respondido, es:
super(B, self).prop
O en Python 3:
super().prop
Esto devuelve el valor devuelto por el captador de la propiedad, no el captador en sí, pero es suficiente para extender el captador.
En B, acceder al conjunto de propiedades de la clase principal A:
La mejor recomendación que he visto hasta ahora es la siguiente:
A.prop.fset(self, value)
Creo que este es mejor:
super(B, self.__class__).prop.fset(self, value)
En este ejemplo, ambas opciones son equivalentes, pero el uso de super tiene la ventaja de ser independiente de las clases base de B
Si B
fuera a heredar de una clase C
también extiende la propiedad, no tendrías que actualizar el código de B
Código completo de B que extiende la propiedad de A:
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)
Una advertencia:
A menos que su propiedad no tenga un setter, debe definir tanto el setter como el getter en B
incluso si solo cambia el comportamiento de uno de ellos.
Estoy cambiando algunas clases de la mía desde un uso extensivo de getters y setters a un uso más pythonic de propiedades.
Pero ahora estoy atascado porque algunos de mis getters o setters anteriores llamaban al método correspondiente de la clase base, y luego realizaban otra cosa. Pero, ¿cómo se puede lograr esto con las propiedades? ¿Cómo llamar a la propiedad getter o setter en la clase principal?
Por supuesto, solo llamar al atributo en sí da una recursión infinita.
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
Podría pensar que podría llamar a la función de clase base a la que llama propiedad:
class FooBar(Foo):
@property
def bar(self):
# return the same value
# as in the base class
return Foo.bar(self)
Aunque creo que es lo más obvio que intento , no funciona porque la barra es una propiedad, no es invocable.
Pero una propiedad es solo un objeto, con un método getter para encontrar el atributo correspondiente:
class FooBar(Foo):
@property
def bar(self):
# return the same value
# as in the base class
return Foo.bar.fget(self)
tratar
@property
def bar:
return super(FooBar, self).bar
Aunque no estoy seguro de si Python admite llamar a la propiedad de la clase base. Una propiedad es en realidad un objeto invocable que se configura con la función especificada y luego reemplaza ese nombre en la clase. Esto podría significar fácilmente que no hay super función disponible.
Sin embargo, siempre puedes cambiar tu sintaxis para usar la función de propiedad ():
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
Super debería hacer el truco:
return super().bar
En Python 2.x necesita usar la sintaxis más detallada:
return super(FooBar, self).bar
class Base(object):
def method(self):
print "Base method was called"
class Derived(Base):
def method(self):
super(Derived,self).method()
print "Derived method was called"
d = Derived()
d.method()
(Es decir, a menos que me falta algo de su explicación)