¿Cómo llamar a una propiedad de la clase base si esta propiedad está siendo sobrescrita en la clase derivada?
Estoy cambiando algunas clases mías de un uso extensivo de getters y setters a un uso más pitónico 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 propiedades? ¿Cómo llamar a la propiedad getter o setter en la clase padre?
Por supuesto, solo llamar al atributo en sí da 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
5 answers
Podría pensar que podría llamar a la función de clase base que se llama por propiedad:
class FooBar(Foo):
@property
def bar(self):
# return the same value
# as in the base class
return Foo.bar(self)
Aunque esta es la cosa más obvia para probar creo - no funciona porque bar es una propiedad, no un callable.
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)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-09-09 18:53:04
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
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-10-30 19:05:10
Existe una alternativa usando super
que no requiere hacer referencia explícita al 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 propiedades de la clase principal A:
Como otros ya han respondido, es:
super(B, self).prop
O en Python 3:
super().prop
Esto devuelve el valor devuelto por el getter de la propiedad, no el getter en sí, pero es suficiente para extender el getter.
En B, acceder a la propiedad setter 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:{[13]]}
super(B, self.__class__).prop.fset(self, value)
En este ejemplo ambas opciones son equivalentes pero usar super tiene la ventaja de ser independiente de las clases base de B
. Si B
fuera a heredar de una clase C
que también extiende la propiedad, no tendría 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)
Uno advertencia:
A menos que su propiedad no tenga un setter, tiene que definir tanto el setter como el getter en B
incluso si solo cambia el comportamiento de uno de ellos.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-05-15 12:27:11
Intenta
@property
def bar:
return super(FooBar, self).bar
Aunque no estoy seguro de si python soporta llamar a la propiedad clase base. Una propiedad es en realidad un objeto llamable 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 una súper función disponible.
Siempre puedes cambiar tu sintaxis para usar la función 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
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-06-20 12:16:06
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 esté perdiendo algo de su explicación)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-06-20 11:51:44