Viktige punkter
- Pythons `super()`-funksjon gir deg muligheten til å aktivere metoder fra overordnede klasser i en underklasse. Dette forenkler implementeringen av arv og overstyring av metoder.
- Funksjonen `super()` er tett knyttet til Metodoppløsningsrekkefølgen (MRO) i Python. MRO definerer rekkefølgen for hvordan Python leter etter metoder eller attributter i overordnede klasser.
- Det er vanlig å bruke `super()` i klassekonstruktører for å initialisere vanlige attributter i overordnede klasser, og mer spesifikke attributter i underklasser. Hvis du unnlater å bruke `super()`, kan dette føre til utilsiktede konsekvenser, som at attributter ikke blir initialisert.
En av de sentrale egenskapene til Python er objektorientert programmering (OOP), som lar deg modellere objekter fra virkeligheten og deres relasjoner.
Når du arbeider med Python-klasser, vil du ofte bruke arv for å overstyre attributter eller metoder fra en overordnet klasse. Python tilbyr `super()`-funksjonen for å kalle metoder fra den overordnede klassen i underklassen.
Hva er `super()`, og hvorfor er den nødvendig?
Gjennom arv kan du opprette en ny Python-klasse som arver egenskapene til en eksisterende klasse. Du kan også overstyre metoder fra overordnede klasser i underklasser for å implementere alternativ funksjonalitet. Det kan likevel være ønskelig å bruke den nye funksjonaliteten i tillegg til den eksisterende, og ikke i stedet for. I slike situasjoner kommer `super()` til nytte.
Du kan bruke `super()` for å få tilgang til attributter og kalle metoder fra den overordnede klassen. `super()` er en viktig funksjon i objektorientert programmering fordi den forenkler arv og metodeoverstyring.
Hvordan fungerer `super()`?
Internt er `super()` tett knyttet til Metodoppløsningsrekkefølgen (MRO) i Python, som bestemmes av C3-lineariseringsalgoritmen.
Slik fungerer `super()`:
- Finn gjeldende klasse og instans: Når `super()` kalles fra en metode i en underklasse, identifiserer Python automatisk den gjeldende klassen (klassen som inneholder metoden som kalte `super()`) og instansen av den klassen (det vil si `self`).
- Bestem den overordnede klassen: `super()` aksepterer to argumenter – den gjeldende klassen og instansen – som du ikke trenger å angi eksplisitt. Den bruker denne informasjonen til å identifisere den overordnede klassen som metodekallet skal delegeres til. Dette gjøres ved å analysere klassehierarkiet og MRO.
- Kall metoden i den overordnede klassen: Når den overordnede klassen er identifisert, lar `super()` deg kalle metodene i den overordnede klassen som om de ble kalt direkte fra underklassen. Dette gir deg muligheten til å utvide eller overstyre metoder mens du likevel beholder den originale implementasjonen fra den overordnede klassen.
Bruk av `super()` i en klassekonstruktør
Det er vanlig å bruke `super()` i en klassekonstruktør, siden du ofte vil initialisere vanlige attributter i den overordnede klassen og mer spesifikke attributter i underklassen.
For å illustrere dette, kan vi definere en Python-klasse, `Father`, som en `Son`-klasse arver fra:
class Father: def __init__(self, first_name, last_name): self.first_name = first_name self.last_name = last_name class Son(Father): def __init__(self, first_name, last_name, age, hobby): super().__init__(first_name, last_name) self.age = age self.hobby = hobby def get_info(self): return f"Sønns navn: {self.first_name} {self.last_name},
Sønns alder: {self.age}, Sønns hobby: {self.hobby}" son = Son("Pius", "Effiong", 25, "Spiller gitar") print(son.get_info())
I `Son`-konstruktøren kaller `super().__init__()` konstruktøren til `Father`-klassen og sender fornavn og etternavn som parametre. Dette sikrer at `Father`-klassen kan sette navneattributtene korrekt, selv på et `Son`-objekt.
Hvis du ikke kaller `super()` i en klassekonstruktør, vil ikke konstruktøren til den overordnede klassen bli kjørt. Dette kan føre til utilsiktede konsekvenser, som manglende initialisering av attributter eller ufullstendig oppsett av tilstanden til den overordnede klassen:
... class Son(Father): def __init__(self, first_name, last_name, age, hobby): self.age = age self.hobby = hobby ...
Hvis du nå prøver å kalle `get_info`-metoden, vil det oppstå en `AttributeError` fordi attributtene `self.first_name` og `self.last_name` ikke er initialisert.
Bruk av `super()` i klassemetoder
Du kan også bruke `super()` i andre metoder, i tillegg til konstruktører, på samme måte. Dette lar deg utvide eller overstyre funksjonaliteten i metoder fra den overordnede klassen.
class Father: def speak(self): return "Hallo fra Far" class Son(Father): def speak(self): parent_greeting = super().speak() return f"Hallo fra Sønn\n{parent_greeting}" son = Son() son_greeting = son.speak() print(son_greeting)
`Son`-klassen arver fra `Father` og har sin egen `speak`-metode. Metoden `speak` i `Son`-klassen bruker `super().speak()` for å kalle `speak`-metoden fra `Father`-klassen. Dette gjør at den kan inkludere meldingen fra den overordnede klassen, samtidig som den legger til en melding som er spesifikk for underklassen.
Hvis du unnlater å bruke `super()` i en metode som overstyrer en annen metode, betyr dette at funksjonaliteten til den overordnede klassens metode ikke vil bli aktivert. Dette fører til at metodeoppførselen blir fullstendig erstattet, noe som kan resultere i utilsiktet oppførsel.
Forstå Metodoppløsningsrekkefølgen (MRO)
Metodoppløsningsrekkefølgen (MRO) er rekkefølgen Python søker etter i overordnede klasser når du får tilgang til en metode eller et attributt. MRO hjelper Python med å bestemme hvilken metode som skal kalles når det finnes flere arvehierarkier.
class Nigeria(): def culture(self): print("Nigeriansk kultur") class Africa(): def culture(self): print("Afrikansk kultur")
Dette skjer når du oppretter en instans av `Lagos`-klassen og kaller `culture`-metoden:
- Python begynner med å se etter `culture`-metoden i selve `Lagos`-klassen. Hvis metoden blir funnet, kalles den. Hvis ikke, går den videre til trinn to.
- Hvis `culture`-metoden ikke finnes i `Lagos`-klassen, vil Python se på basisklassene i den rekkefølgen de er oppført i klassedefinisjonen. I dette tilfellet arver `Lagos` først fra `Africa` og deretter fra `Nigeria`. Python vil derfor se etter `culture`-metoden i `Africa` først.
- Hvis `culture`-metoden ikke finnes i `Africa`-klassen, vil Python se etter den i `Nigeria`-klassen. Dette fortsetter til den når slutten av hierarkiet og gir en feilmelding hvis metoden ikke finnes i noen av de overordnede klassene.
Utdataene viser metodoppløsningsrekkefølgen til `Lagos`, fra venstre til høyre.
Vanlige feil og beste praksis
Når du arbeider med `super()`, er det noen vanlige feil du bør unngå.
- Vær oppmerksom på metodoppløsningsrekkefølgen, spesielt i komplekse scenarioer med flere arv. Hvis du skal bruke avansert multippel arv, bør du være kjent med C3-lineariseringsalgoritmen som Python bruker for å bestemme MRO.
- Unngå sirkulære avhengigheter i klassehierarkiet ditt, da dette kan føre til uforutsigbar oppførsel.
- Dokumenter koden din tydelig, spesielt når du bruker `super()` i komplekse klassehierarkier, for å gjøre den lettere å forstå for andre utviklere.
Bruk `super()` på riktig måte
Pythons `super()`-funksjon er et kraftig verktøy når du jobber med arv og metodeoverstyring. Ved å forstå hvordan `super()` fungerer og ved å følge beste praksis, kan du skrive mer vedlikeholdbar og effektiv kode i Python-prosjektene dine.