Arv är användbart, men du kan låsa upp dess fulla potential genom att återanvända kod från basklasser.
Viktiga takeaways
- Pythons super()-funktion låter dig anropa superklassmetoder från en underklass, vilket gör det lättare att implementera arv och metodöverstyrning.
- Super()-funktionen är nära relaterad till Method Resolution Order (MRO) i Python, som bestämmer i vilken ordning förfäderklasser söks efter metoder eller attribut.
- Att använda super() i klasskonstruktörer är vanligt att initiera vanliga attribut i den överordnade klassen och mer specifika i den underordnade klassen. Att misslyckas med att använda super() kan leda till oavsiktliga konsekvenser, som att attributinitiering saknas.
En av kärnfunktionerna i Python är dess OOP-paradigm, som du kan använda för att modellera verkliga enheter och deras relationer.
När du arbetar med Python-klasser använder du ofta arv och åsidosätter en superklasss attribut eller metoder. Python tillhandahåller en super() funktion som låter dig anropa superklassens metoder från underklassen.
Vad är super() och varför behöver du det?
Genom att använda arv kan du skapa en ny Python-klass som ärver funktionerna i en befintlig klass. Du kan också åsidosätta metoder för superklassen i underklassen, vilket ger alternativa implementeringar. Men du kanske vill använda den nya funktionen utöver den gamla istället för den. I detta fall, super() är användbar.
Du kan använda super() funktion för att komma åt superklassattribut och anropa metoder för superklassen. Super är viktigt för objektorienterad programmering eftersom det gör det lättare att implementera arv och metodöverstyrning.
Hur fungerar super()?
Internt, super() är nära besläktad med Metodupplösningsordning (MRO) i Python, som C3-lineariseringsalgoritmen bestämmer.
Här är hur super() Arbetar:
- Bestäm aktuell klass och instans: När du ringer super() inuti en metod för en underklass räknar Python automatiskt ut den aktuella klassen (klassen som innehåller metoden som anropade super()) och instansen av den klassen (dvs. själv).
- Bestäm superklassen: super() tar två argument – den aktuella klassen och instansen – som du inte behöver ange uttryckligen. Den använder denna information för att bestämma superklassen för att delegera metodanropet. Den gör detta genom att undersöka klasshierarkin och MRO.
- Anropa metoden på Superklassen: När det har bestämts superklassen, super() låter dig anropa dess metoder som om du anropade dem direkt från underklassen. Detta gör att du kan utöka eller åsidosätta metoder medan du fortfarande använder den ursprungliga implementeringen från superklassen.
Använda super() i en klasskonstruktör
Använder sig av super() i en klasskonstruktor är vanlig praxis, eftersom du ofta vill initiera vanliga attribut i den överordnade klassen och mer specifika i barnet.
För att visa detta, definiera en Python-klass, Far, vilken ett, vilken en Son klass ärver från:
classFather:
def__init__(self, first_name, last_name):
self.first_name = first_name
self.last_name = last_nameclassSon(Father):
def__init__(self, first_name, last_name, age, hobby):
# Call the parent class constructor (Father)
super().__init__(first_name, last_name)self.age = age
self.hobby = hobbydefget_info(self):
returnf"Son's Name: {self.first_name}{self.last_name}, \
Son's Age: {self.age}, Son's Hobby: {self.hobby}"# Create an instance of the Son class
son = Son("Pius", "Effiong", 25, "Playing Guitar")
# Access attributes
print(son.get_info())
Inuti Son konstruktör, uppmaningen till super().init() åberopar Far klasskonstruktör, klarar den förnamn och efternamn som parametrar. Detta säkerställer att Far klass kan fortfarande ställa in namnattributen korrekt, även på en Son objekt.
Om du inte ringer super() i en klasskonstruktor kommer konstruktören för dess överordnade klass inte att köras. Detta kan leda till oavsiktliga konsekvenser, såsom saknade attributinitieringar eller ofullständig inställning av den överordnade klassens tillstånd:
...
classSon(Father):
def__init__(self, first_name, last_name, age, hobby):
self.age = age
self.hobby = hobby
...
Om du nu försöker ringa till få information metod kommer det att höja en AttributeError eftersom den self.first_name och själv.efternamn attribut har inte initierats.
Använder super() i klassmetoder
Du kan använda super() i andra metoder, förutom konstruktörer, på precis samma sätt. Detta låter dig utöka eller åsidosätta beteendet för superklassens metod.
classFather:
defspeak(self):
return"Hello from Father"classSon(Father):
defspeak(self):
# Call the parent class's speak method using super()
parent_greeting = super().speak()
returnf"Hello from Son\n{parent_greeting}"# Create an instance of the Son class
son = Son()# Call the speak method of the Son class
son_greeting = son.speak()
print(son_greeting)
De Son klass ärver från Far och har sin tala metod. De tala metod för Son klass använder super().speak() att ringa till tala metod för Far klass. Detta gör att den kan inkludera meddelandet från den överordnade klassen samtidigt som det utökas med ett meddelande specifikt för den underordnade klassen.
Misslyckas att använda super() i en metod som åsidosätter en annan betyder det att funktionaliteten i den överordnade klassmetoden inte kommer att träda i kraft. Detta resulterar i en fullständig ersättning av metodbeteendet, vilket kan leda till beteende som du inte tänkt.
Förstå metodupplösningsordning
Method Resolution Order (MRO) är den ordning i vilken Python söker efter förfäderklasser när du kommer åt en metod eller ett attribut. MRO hjälper Python att avgöra vilken metod som ska anropas när det finns flera arvshierarkier.
classNigeria():
defculture(self):
print("Nigeria's culture")
classAfrica():
defculture(self):
print("Africa's culture")
Här är vad som händer när du skapar en instans av Lagos klass och ring kultur metod:
- Python börjar med att leta efter kultur metod i Lagos klassen själv. Om den hittar den, anropar den metoden. Om inte går den vidare till steg två.
- Om den inte hittar kultur metod i Lagos klass, tittar Python på basklasserna i den ordning de visas i klassdefinitionen. I detta fall, Lagos ärver först från Afrika och sedan från Nigeria. Så, Python kommer att leta efter kultur metod i Afrika först.
- Om den inte hittar kultur metod i Afrika klass kommer Python sedan att titta i Nigeria klass. Detta beteende fortsätter tills det når slutet av hierarkin och ger ett fel om det inte kan hitta metoden i någon av superklasserna.
Utdata visar metodupplösningsordningen för Lagos, med början från vänster till höger.
Vanliga fallgropar och bästa praxis
När man arbetar med super(), det finns några vanliga fallgropar att undvika.
- Var uppmärksam på metodupplösningsordningen, särskilt i scenarier för flera arv. Om du behöver använda komplext multipelarv bör du vara bekant med C3 Lineariseringsalgoritm som Python använder för att bestämma MRO.
- Undvik cirkulära beroenden i din klasshierarki, vilket kan leda till oförutsägbart beteende.
- Dokumentera din kod tydligt, speciellt vid användning super() i komplexa klasshierarkier, för att göra det mer begripligt för andra utvecklare.
Använd super() på rätt sätt
Pythons super() funktion är en kraftfull funktion när du arbetar med arv och metodöverstyrning. Förstå hur super() fungerar och att följa bästa praxis låter dig skapa mer underhållbar och effektiv kod i dina Python-projekt.