poo - llamar una clase dentro de otra clase python
¿Llamar a un método de clase padre de clase hijo en Python? (14)
Al crear una jerarquía de objetos simple en Python, me gustaría poder invocar métodos de la clase padre desde una clase derivada. En Perl y Java, hay una palabra clave para esto ( super
). En Perl, podría hacer esto:
package Foo;
sub frotz {
return "Bamf";
}
package Bar;
@ISA = qw(Foo);
sub frotz {
my $str = SUPER::frotz();
return uc($str);
}
En Python, parece que tengo que nombrar la clase padre explícitamente del hijo. En el ejemplo anterior, tendría que hacer algo como Foo::frotz()
.
Esto no parece correcto, ya que este comportamiento hace que sea difícil hacer jerarquías profundas. Si los niños necesitan saber qué clase definió un método heredado, entonces se crea todo tipo de dolor de información.
¿Es esta una limitación real en Python, una brecha en mi comprensión o ambas?
Aquí hay un ejemplo del uso de super () :
#New-style classes inherit from object, or from another new-style class
class Dog(object):
name = ''''
moves = []
def __init__(self, name):
self.name = name
def moves_setup(self):
self.moves.append(''walk'')
self.moves.append(''run'')
def get_moves(self):
return self.moves
class Superdog(Dog):
#Let''s try to append new fly ability to our Superdog
def moves_setup(self):
#Set default moves by calling method of parent class
super(Superdog, self).moves_setup()
self.moves.append(''fly'')
dog = Superdog(''Freddy'')
print dog.name # Freddy
dog.moves_setup()
print dog.get_moves() # [''walk'', ''run'', ''fly''].
#As you can see our Superdog has all moves defined in the base Dog class
En Python 2, no tuve mucha suerte con super (). Utilicé la respuesta de jimifiki en este hilo SO ¿cómo referirme a un método primario en python? . Luego, le agregué mi propio pequeño giro, que creo que es una mejora en la usabilidad (especialmente si tienes nombres de clase largos).
Defina la clase base en un módulo:
# myA.py
class A():
def foo( self ):
print "foo"
Luego importa la clase en otros módulos as parent
:
# myB.py
from myA import A as parent
class B( parent ):
def foo( self ):
parent.foo( self ) # calls ''A.foo()''
Este es un método más abstracto:
super(self.__class__,self).baz(arg)
Muchas respuestas han explicado cómo llamar a un método del padre que se ha invalidado en el hijo.
sin embargo
"¿Cómo llamas al método de una clase padre de una clase hijo?"
También podría significar simplemente:
"¿Cómo se llama métodos heredados?"
Puede llamar a métodos heredados de una clase principal como si fueran métodos de la clase secundaria, siempre que no se hayan sobrescrito.
Por ejemplo, en Python 3:
class A():
def bar(self, string):
print("Hi, I''m bar, inherited from A"+string)
class B(A):
def baz(self):
self.bar(" - called by baz in B")
B().baz() # prints out "Hi, I''m bar, inherited from A - called by baz in B"
Sí, esto puede ser bastante obvio, pero creo que sin señalar esto, las personas pueden dejar este hilo con la impresión de que tienes que saltar a través de aros ridículos solo para acceder a los métodos heredados en Python. Especialmente ya que esta pregunta tiene una alta calificación en las búsquedas de "cómo acceder al método de una clase padre en Python", y el OP se escribe desde la perspectiva de alguien nuevo en python.
Encontré: https://docs.python.org/3/tutorial/classes.html#inheritance para ser útil en la comprensión de cómo acceder a los métodos heredados.
Python 3 tiene una sintaxis diferente y más simple para llamar al método principal. Si la clase Foo
hereda de Bar
, entonces desde Bar.__init__
se puede invocar desde Foo
usando super().__init__()
:
class Foo(Bar):
def __init__(self):
super().__init__()
Python también tiene super también:
super (type[, object-or-type])
Devuelva un objeto proxy que delegue las llamadas de método a una clase de tipo padre o hermana. Esto es útil para acceder a los métodos heredados que se han anulado en una clase. El orden de búsqueda es el mismo que el utilizado por getattr (), excepto que se omite el propio tipo.
Ejemplo:
class A(object): # deriving from ''object'' declares A as a ''new-style-class''
def foo(self):
print "foo"
class B(A):
def foo(self):
super(B, self).foo() # calls ''A.foo()''
myB = B()
myB.foo()
Recomendaría usar CLASS.__bases__
algo como esto
class A:
def __init__(self):
print "I am Class %s"%self.__class__.__name__
for parentClass in self.__class__.__bases__:
print " I am inherited from:",parentClass.__name__
#parentClass.foo(self) <- call parents function with self as first param
class B(A):pass
class C(B):pass
a,b,c = A(),B(),C()
Sí, pero solo con clases de nuevo estilo . Utilice la función super()
:
class Foo(Bar):
def baz(self, arg):
return super(Foo, self).baz(arg)
Si no sabe cuántos argumentos puede obtener y desea transmitirlos también al niño:
class Foo(bar)
def baz(self, arg, *args, **kwargs):
# ... Do your thing
return super(Foo, self).baz(arg, *args, **kwargs)
También hay un super () en Python. Es un poco extraño, debido a las clases de estilo antiguo y nuevo de Python, pero se usa con bastante frecuencia, por ejemplo, en constructores:
class Foo(Bar):
def __init__(self):
super(Foo, self).__init__()
self.baz = 5
También hay un super () en python.
Ejemplo de cómo se llama a un método de superclase desde un método de subclase
class Dog(object):
name = ''''
moves = []
def __init__(self, name):
self.name = name
def moves_setup(self,x):
self.moves.append(''walk'')
self.moves.append(''run'')
self.moves.append(x)
def get_moves(self):
return self.moves
class Superdog(Dog):
#Let''s try to append new fly ability to our Superdog
def moves_setup(self):
#Set default moves by calling method of parent class
super().moves_setup("hello world")
self.moves.append(''fly'')
dog = Superdog(''Freddy'')
print (dog.name)
dog.moves_setup()
print (dog.get_moves())
Este ejemplo es similar al explicado anteriormente. Sin embargo, hay una diferencia de que super no tiene argumentos pasados. Este código anterior es ejecutable en la versión Python 3.4.
en este ejemplo, cafec_param es una clase base (clase padre) y abc es una clase hijo. abc llama al método AWC en la clase base.
class cafec_param:
def __init__(self,precip,pe,awc,nmonths):
self.precip = precip
self.pe = pe
self.awc = awc
self.nmonths = nmonths
def AWC(self):
if self.awc<254:
Ss = self.awc
Su = 0
self.Ss=Ss
else:
Ss = 254; Su = self.awc-254
self.Ss=Ss + Su
AWC = Ss + Su
return self.Ss
def test(self):
return self.Ss
#return self.Ss*4
class abc(cafec_param):
def rr(self):
return self.AWC()
ee=cafec_param(''re'',34,56,2)
dd=abc(''re'',34,56,2)
print(dd.rr())
print(ee.AWC())
print(ee.test())
Salida
56
56
56
ImmediateParentClass.frotz(self)
Estará bien, ya sea que la clase padre inmediata se haya definido frotz
o se haya heredado. super
solo es necesario para el soporte adecuado de herencia múltiple (y luego solo funciona si cada clase lo usa adecuadamente). En general, AnyClass.whatever
buscará whatever
en los antepasados de AnyClass
si AnyClass
no lo define / anula, y esto es válido para el "método hijo de los padres que llaman clase" ¡como para cualquier otro evento!
class a(object):
def my_hello(self):
print "hello ravi"
class b(a):
def my_hello(self):
super(b,self).my_hello()
print "hi"
obj = b()
obj.my_hello()