Podczas tworzenia prostej hierarchii obiektów w Pythonie chciałbym móc wywoływać metody klasy nadrzędnej z klasy pochodnej. W Perlu i Javie istnieje słowo kluczowe dla tego ( super
). W Perlu mogę to zrobić:
package Foo;
sub frotz {
return "Bamf";
}
package Bar;
@ISA = qw(Foo);
sub frotz {
my $str = SUPER::frotz();
return uc($str);
}
W Pythonie wydaje się, że muszę wyraźnie nazwać klasę nadrzędną od dziecka. W powyższym przykładzie musiałbym zrobić coś takiego Foo::frotz()
.
Nie wydaje się to właściwe, ponieważ takie zachowanie utrudnia tworzenie głębokich hierarchii. Jeśli dzieci muszą wiedzieć, która klasa zdefiniowała odziedziczoną metodę, powstają różnego rodzaju bóle informacyjne.
Czy to rzeczywiste ograniczenie w pythonie, luka w moim rozumieniu, czy jedno i drugie?
python
inheritance
class
object
jjohn
źródło
źródło
Odpowiedzi:
Tak, ale tylko z klasami w nowym stylu . Użyj
super()
funkcji:W przypadku python <3 użyj:
źródło
super(Foo, self)
jest zgodna z Python 2.x? W Pythonie 3.xsuper()
preferowana jest poprawna?Python ma również super :
super(type[, object-or-type])
Przykład:
źródło
będzie dobrze, bez względu na to, czy bezpośrednia klasa nadrzędna zdefiniowała
frotz
się, czy odziedziczyła.super
jest potrzebny tylko do prawidłowej obsługi wielokrotnego dziedziczenia (a wtedy działa tylko wtedy, gdy każda klasa używa go poprawnie). Ogólnie rzecz biorąc,AnyClass.whatever
będzie patrzećwhatever
wAnyClass
„s przodków jeśliAnyClass
nie definiuje / nadpisać go, a to odnosi się do«klasy dziecięcej wywołanie metody rodzica», jak dla każdego innego wystąpienia!źródło
parent
, to należy do całej klasy, prawda?Python 3 ma inną i prostszą składnię do wywoływania metody nadrzędnej.
Jeśli
Foo
klasa dziedziczy poBar
, toBar.__init__
można wywołać z fromFoo
za pośrednictwemsuper().__init__()
:źródło
Wiele odpowiedzi wyjaśniło, jak wywołać metodę nadrzędną, która została zastąpiona przez dziecko.
jednak
może również oznaczać:
Możesz wywoływać metody dziedziczone z klasy nadrzędnej tak, jakby były metodami klasy podrzędnej, o ile nie zostały zastąpione.
np. w python 3:
tak, może to być dość oczywiste, ale czuję, że bez wskazania tego, ludzie mogą zostawić ten wątek z wrażeniem, że musisz skakać przez absurdalne obręcze tylko po to, aby uzyskać dostęp do odziedziczonych metod w pythonie. Zwłaszcza, że to pytanie jest bardzo cenne w wyszukiwaniu „jak uzyskać dostęp do metody klasy nadrzędnej w Pythonie”, a OP jest napisane z perspektywy kogoś nowego w Pythonie.
Uważam, że: https://docs.python.org/3/tutorial/classes.html#inheritance jest przydatny w zrozumieniu, w jaki sposób uzyskujesz dostęp do odziedziczonych metod.
źródło
self.string
nic nie da. W klasie C można jednak jeszcze zadzwonićB().bar(string)
Oto przykład użycia super () :
źródło
W Pythonie jest też super (). Jest nieco nieporadny z powodu klas starego i nowego stylu Pythona, ale jest dość powszechnie stosowany np. W konstruktorach:
źródło
Poleciłbym użycie
CLASS.__bases__
czegoś takiegoźródło
Jeśli nie wiesz, ile argumentów możesz uzyskać, i chcesz przekazać je również dziecku:
(Od: Python - Najczystszy sposób na przesłonięcie __init__, gdzie po wywołaniu super () należy użyć opcjonalnego kwarga? )
źródło
W pythonie znajduje się również super ().
Przykład wywołania metody superklasy z metody podklasy
Ten przykład jest podobny do tego wyjaśnionego powyżej, jednak istnieje jedna różnica polegająca na tym, że super nie ma żadnych argumentów. Powyższy kod jest wykonywalny w wersji Python 3.4.
źródło
W tym przykładzie
cafec_param
jest to klasa podstawowa (klasa nadrzędna) iabc
klasa podrzędna.abc
wywołujeAWC
metodę w klasie bazowej.Wynik
źródło
W Pythonie 2 nie miałem dużo szczęścia z super (). Użyłem odpowiedzi z jimifiki w tym wątku SO, jak odwoływać się do metody nadrzędnej w pythonie? . Następnie dodałem do tego swój własny mały zwrot, który moim zdaniem poprawia użyteczność (szczególnie jeśli masz długie nazwy klas).
Zdefiniuj klasę podstawową w jednym module:
Następnie zaimportuj klasę do innych modułów
as parent
:źródło
class A(object):
zamiastclass A():
wtedy super () zadziałaźródło
źródło
To jest bardziej abstrakcyjna metoda:
źródło
super(self.__class__, self).baz(arg)
.