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 parente à 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.
Est-ce une limitation réelle en python, une lacune dans ma compréhension ou les deux?
Oui, mais seulement avec classes de style nouvea . 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)
Python a aussi super aussi:
super(type[, object-or-type])
Renvoie un objet proxy qui délègue des appels de méthode à une classe parent ou parent du type. 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)
tout ira bien, que la classe parente immédiate définie frotz
elle-même ou qu’elle en ait hérité. super
n'est nécessaire que pour le support correct de l'héritage multiple (et cela ne fonctionne que si toutes les classes l'utilisent correctement). En général, AnyClass.whatever
va rechercher whatever
dans les ancêtres de AnyClass
si AnyClass
ne le définit pas/ne le définit pas, ce qui est vrai pour "la méthode du parent appelant une classe enfant "comme pour tout autre événement!
Python a une syntaxe différente et plus simple pour appeler une méthode parent.
Si Foo
la classe hérite de Bar
, alors de Bar.__init__
peut être appelé à partir de Foo
via super().__init__()
:
class Foo(Bar):
def __init__(self, *args, **kwargs):
# invoke Bar.__init__
super().__init__(*args, **kwargs)
Beaucoup de réponses ont expliqué comment appeler une méthode du parent qui a été remplacée par l'enfant.
Pourtant
"comment appelez-vous la méthode d'une classe parent à partir de la classe enfant?"
pourrait aussi signifier:
"comment appelez-vous les méthodes héritées?"
Vous pouvez appeler des méthodes héritées d'une classe parente comme s'il s'agissait de méthodes de la classe enfant, à condition qu'elles n'aient pas été écrasées.
par exemple. dans 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 l’impression 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 beaucoup d'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 utile pour comprendre comment vous accédez 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 () dans 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 ceci
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 avoir et que vous 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)
Il y a un super () dans python également.
Exemple pour appeler 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 n'a été transmis à super. Ce code ci-dessus est exécutable dans la version python 3.4.
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
Dans Python 2, je n'ai pas eu beaucoup de chance avec super (). J'ai utilisé la réponse de jimifiki sur ce SO thread comment 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 as parent
:
# myB.py
from myA import A as parent
class B( parent ):
def foo( self ):
parent.foo( self ) # calls 'A.foo()'
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()