Appelez la méthode d'une classe parent à partir de la classe enfant en Python?
-
03-07-2019 - |
Question
Lors de la création d'une hiérarchie d'objet simple en Python, j'aimerais pouvoir appeler les méthodes de la classe parente à partir d'une classe dérivée. En Perl et Java, il existe un mot clé pour cela ( super
). En Perl, je pourrais faire ceci:
package Foo;
sub frotz {
return "Bamf";
}
package Bar;
@ISA = qw(Foo);
sub frotz {
my $str = SUPER::frotz();
return uc($str);
}
En python, il apparaît que je dois nommer explicitement la classe parent à partir de l'enfant.
Dans l'exemple ci-dessus, je devrais faire quelque chose comme Foo :: frotz ()
.
Cela ne semble pas correct, car ce comportement rend difficile la création de hiérarchies profondes. Si les enfants ont besoin de savoir quelle classe a défini une méthode héritée, toutes sortes d'informations douloureuses sont créées.
S'agit-il d'une limitation réelle en python, d'une lacune dans ma compréhension ou des deux?
La solution
Oui, mais uniquement avec les classes de style nouveau . Utilisez la fonction super ()
:
class Foo(Bar):
def baz(self, arg):
return super(Foo, self).baz(arg)
Pour Python 3.x, vous pouvez utiliser:
class Foo(Bar):
def baz(self, arg):
return super().baz(arg)
Autres conseils
Python possède également super :
super (type [, objet ou type])
Renvoie un objet proxy qui délègue des appels de méthode à une classe de type parent ou sœur. Ceci est utile pour accéder aux méthodes héritées qui ont été remplacées dans une classe. L'ordre de recherche est identique à celui utilisé par getattr (), sauf que le type lui-même est ignoré.
Exemple:
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()
ImmediateParentClass.frotz(self)
ira très bien, que la classe parente immédiate ait défini frotz
elle-même ou qu’elle en ait hérité. super
n'est nécessaire que pour la prise en charge correcte de l'héritage multiple (et il ne fonctionne ensuite que si chaque classe l'utilise correctement). En général, AnyClass.w Whatever
va rechercher quel que soit
dans les ancêtres de AnyClass
si AnyClass
ne le fait pas. définissez-le / remplacez-le, et cela est vrai pour "la méthode du parent appelant une classe enfant". comme pour tout autre événement!
Python 3 utilise une syntaxe différente et plus simple pour appeler une méthode parent.
Si la classe Foo
hérite de Bar
, puis de Bar .__ init __
peut être appelé à partir de Foo
via < code> super () .__ init __ () :
class Foo(Bar):
def __init__(self, *args, **kwargs):
# invoke Bar.__init__
super().__init__(*args, **kwargs)
De nombreuses réponses ont expliqué comment appeler une méthode du parent qui a été remplacée par l'enfant.
Cependant
"Comment appelez-vous la méthode d'une classe parent à partir d'une classe enfant?"
pourrait aussi simplement signifier:
"Comment appelez-vous les méthodes héritées?"
Vous pouvez appeler des méthodes héritées d'une classe parent comme si elles étaient des méthodes de la classe enfant, tant qu'elles n'ont pas été écrasées.
par exemple. 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"
oui, cela peut paraître assez évident, mais j’ai le sentiment que, sans le signaler, il est possible que des personnes laissent ce fil avec l’impression que vous devez sauter à travers des cercles ridicules pour accéder aux méthodes héritées en python. D'autant plus que cette question accorde une grande importance aux recherches sur "comment accéder à la méthode d'une classe parente en Python", et que l'OP est écrit du point de vue de quelqu'un de novice en python.
j'ai trouvé: https://docs.python.org/3/tutorial/classes.html#inheritance pour vous aider à comprendre comment accéder aux méthodes héritées.
Voici un exemple d'utilisation 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
Il y a aussi un super () en Python. C'est un peu bizarre, à cause des classes de style ancien et nouveau de Python, mais il est assez couramment utilisé, par exemple. dans les constructeurs:
class Foo(Bar):
def __init__(self):
super(Foo, self).__init__()
self.baz = 5
Je recommanderais d'utiliser CLASS .__ bases __
quelque chose comme ça
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()
Si vous ne connaissez pas le nombre d'arguments que vous pourriez obtenir et souhaitez également les transmettre à l'enfant:
class Foo(bar)
def baz(self, arg, *args, **kwargs):
# ... Do your thing
return super(Foo, self).baz(arg, *args, **kwargs)
(De: )
Il existe également un super () en python.
Exemple d'utilisation d'une méthode de super classe à partir d'une méthode de sous-classe
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())
Cet exemple est similaire à celui expliqué ci-dessus. Il existe toutefois une différence: aucun argument ne lui est transmis par super.Ce code ci-dessus est exécutable dans la version 3.4 de Python.
En Python 2, je n’avais pas beaucoup de chance avec super (). J'ai utilisé la réponse de comment jimifiki sur ce fil SO faire référence à une méthode parente en python ? . Ensuite, j’y ai ajouté ma petite touche personnelle, ce qui, à mon avis, constitue une amélioration de la convivialité (surtout si vous avez des noms de classe longs).
Définissez la classe de base dans un module:
# myA.py
class A():
def foo( self ):
print "foo"
Importez ensuite la classe dans un autre module en tant que parent
:
# myB.py
from myA import A as parent
class B( parent ):
def foo( self ):
parent.foo( self ) # calls 'A.foo()'
dans cet exemple cafec_param est une classe de base (classe parent) et abc est une classe enfant. abc appelle la méthode AWC dans la classe de 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())
Sortie
56
56
56
class department:
campus_name="attock"
def printer(self):
print(self.campus_name)
class CS_dept(department):
def overr_CS(self):
department.printer(self)
print("i am child class1")
c=CS_dept()
c.overr_CS()
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()
Ceci est une méthode plus abstraite:
super(self.__class__,self).baz(arg)