# 9. Klasser

Klasser är ett sätt att paketera data och funktionalitet tillsammans. Genom att skapa en ny klass skapas en ny typ av objekt, vilket gör det möjligt att skapa nya instanser av den typen. Varje klassinstans kan ha attribut kopplade till sig för att bibehålla sitt tillstånd. Klassinstanser kan också ha metoder (definierade av klassen) för att ändra sitt tillstånd.

Jämfört med andra programmeringsspråk lägger Pythons klassmekanism till klasser med ett minimum av ny syntax och semantik. Det är en blandning av de klassmekanismer som finns i C++ och Modula-3. Python-klasser har alla standardfunktioner för objektorienterad programmering: klassens arvsmekanism tillåter flera basklasser, en härledd klass kan åsidosätta alla metoder i sin basklass eller sina basklasser och en metod kan anropa metoden i en basklass med samma namn. Objekt kan innehålla godtyckliga mängder och typer av data. Precis som för moduler är klasser en del av Pythons dynamiska natur: de skapas under körning och kan modifieras ytterligare efter skapandet.

I C++-terminologi är klassmedlemmar (inklusive datamedlemmar) normalt public (utom se nedan Privata variabler) och alla medlemsfunktioner är virtuella. Precis som i Modula-3 finns det inga kortkommandon för att referera till objektets medlemmar från dess metoder: metodfunktionen deklareras med ett explicit första argument som representerar objektet, vilket tillhandahålls implicit av anropet. Precis som i Smalltalk är klasserna i sig själva objekt. Detta ger semantik för import och namnändring. Till skillnad från C++ och Modula-3 kan inbyggda typer användas som basklasser för utvidgning av användaren. Precis som i C++ kan de flesta inbyggda operatorer med speciell syntax (aritmetiska operatorer, subskription etc.) omdefinieras för klassinstanser.

(I brist på allmänt accepterad terminologi för att tala om klasser kommer jag ibland att använda Smalltalk- och C++-termer. Jag skulle använda Modula-3-termer, eftersom dess objektorienterade semantik ligger närmare Python än C++, men jag förväntar mig att få läsare har hört talas om det)

## 9.1. Några ord om namn och objekt

Objekten är individuella och flera namn (i flera scopes) kan bindas till samma objekt. Detta är känt som aliasing i andra språk. Detta uppskattas vanligtvis inte vid en första anblick av Python, och kan säkert ignoreras när man hanterar oföränderliga bastyper (tal, strängar, tupler). Aliasing har dock en möjligen överraskande effekt på semantiken i Python-kod som involverar föränderliga objekt som listor, ordböcker och de flesta andra typer. Detta används vanligtvis till förmån för programmet, eftersom alias beter sig som pekare i vissa avseenden. Till exempel är det billigt att skicka ett objekt eftersom endast en pekare skickas av implementationen; och om en funktion ändrar ett objekt som skickas som ett argument kommer den som anropar att se förändringen — detta eliminerar behovet av två olika mekanismer för argumentpassning som i Pascal.

## 9.2. Python Scopes och namnrymder

Innan jag introducerar klasser måste jag först berätta något om Pythons scope-regler. Klassdefinitioner spelar några snygga trick med namnrymder, och du måste veta hur scopes och namnrymder fungerar för att förstå vad som händer. För övrigt är kunskap om detta ämne användbart för alla avancerade Python-programmerare.

Låt oss börja med några definitioner.

En namnrymd är en mappning från namn till objekt. De flesta namnrymder är för närvarande implementerade som Python-ordlistor, men det är normalt inte märkbart på något sätt (förutom prestanda), och det kan ändras i framtiden. Exempel på namnrymder är: uppsättningen inbyggda namn (som innehåller funktioner som `abs()` och inbyggda namn på undantag), de globala namnen i en modul och de lokala namnen i en funktionsinstruktion. På sätt och vis utgör också uppsättningen av attribut för ett objekt ett namnrymd. Det viktiga att veta om namnrymder är att det inte finns någon som helst relation mellan namn i olika namnrymder; till exempel kan två olika moduler båda definiera en funktion `maximize` utan förvirring — användare av modulerna måste prefixera den med modulnamnet.

Förresten, jag använder ordet attribut för alla namn som följer efter en punkt — till exempel, i uttrycket `z.real` är `real` ett attribut för objektet `z`. I strikt mening är referenser till namn i moduler attributreferenser: i uttrycket `modname.funcname` är `modname` ett modulobjekt och `funcname` är ett attribut till det. I det här fallet råkar det finnas en enkel mappning mellan modulens attribut och de globala namn som definieras i modulen: de delar samma namnrymd! [1]

Attributen kan vara skrivskyddade eller skrivbara. I det senare fallet är det möjligt att tilldela attribut. Modulattribut är skrivbara: du kan skriva `modname.the_answer = 42`. Skrivbara attribut kan också tas bort med `del`. Till exempel, `del modname.the_answer` kommer att ta bort attributet `the_answer` från objektet som heter `modname`.

Namnrymder skapas vid olika tidpunkter och har olika livslängd. Namnrymden som innehåller de inbyggda namnen skapas när Python-tolken startar och raderas aldrig. Det globala namnrymden för en modul skapas när moduldefinitionen läses in; normalt varar modulnamnrymder också tills tolken avslutas. De satser som utförs av tolkens anrop på toppnivå, antingen inlästa från en skriptfil eller interaktivt, betraktas som en del av en modul som heter `__main__`, och de har därför ett eget globalt namnrymd. (De inbyggda namnen finns faktiskt också i en modul; denna kallas `builtins`)

Det lokala namnrymden för en funktion skapas när funktionen anropas och raderas när funktionen returneras eller ger upphov till ett undantag som inte hanteras inom funktionen. (Egentligen skulle ”glömma” vara ett bättre sätt att beskriva vad som faktiskt händer) Naturligtvis har rekursiva anrop alla sina egna lokala namnrymder.

En scope är en textuell region i ett Python-program där en namnrymd är direkt åtkomlig. ”Direkt åtkomlig” betyder här att en okvalificerad referens till ett namn försöker hitta namnet i namnrymden.

Även om scopes bestäms statiskt används de dynamiskt. När som helst under exekveringen finns det 3 eller 4 nästlade scopes vars namnrymder är direkt åtkomliga:

- det innersta omfånget, som söks först, innehåller de lokala namnen

- scopen för alla inneslutande funktioner, som genomsöks med början från närmaste inneslutande scope, innehåller icke-lokala, men även icke-globala namn

- det näst sista omfånget innehåller den aktuella modulens globala namn

- det yttersta omfånget (söks sist) är namnrymden som innehåller inbyggda namn

Om ett namn deklareras som globalt, går alla referenser och tilldelningar direkt till det näst sista scope som innehåller modulens globala namn. För att återbinda variabler som finns utanför det innersta scopet kan `nonlocal` användas; om de inte deklareras som icke-lokala är dessa variabler skrivskyddade (ett försök att skriva till en sådan variabel skapar helt enkelt en ny lokal variabel i det innersta scopet, medan den identiskt namngivna yttre variabeln lämnas oförändrad).

Vanligtvis refererar det lokala omfånget till de lokala namnen på den (textuellt) aktuella funktionen. Utanför funktioner refererar det lokala omfånget till samma namnrymd som det globala omfånget: modulens namnrymd. Klassdefinitioner placerar ytterligare en namnrymd i det lokala omfånget.

Det är viktigt att inse att omfattningar bestäms textuellt: den globala omfattningen av en funktion som definieras i en modul är den modulens namnrymd, oavsett varifrån eller med vilket alias funktionen anropas. Å andra sidan görs den faktiska sökningen efter namn dynamiskt, vid körning — språkdefinitionen utvecklas dock mot statisk namnupplösning, vid ”kompileringstid”, så lita inte på dynamisk namnupplösning! (Faktum är att lokala variabler redan bestäms statiskt)

En speciell finess med Python är att – om inget `global` eller `nonlocal` statement är i kraft – assignments till namn alltid går in i det innersta scope. Tilldelningar kopierar inte data — de binder bara namn till objekt. Detsamma gäller för borttagningar: uttalandet `del x` tar bort bindningen av `x` från det namnrymd som refereras av det lokala scopet. Faktum är att alla operationer som introducerar nya namn använder det lokala omfånget: i synnerhet `import`-satser och funktionsdefinitioner binder modul- eller funktionsnamnet i det lokala omfånget.

Satsen `global` kan användas för att ange att vissa variabler finns i det globala omfånget och bör återföras dit; satsen `nonlocal` anger att vissa variabler finns i ett omslutande omfång och bör återföras dit.

### 9.2.1. Exempel på scopes och namnrymder

Detta är ett exempel som visar hur man refererar till olika scopes och namnrymder, och hur `global` och `nonlocal` påverkar variabelbindning:

    def scope_test():
        def do_local():
            spam = "lokal spam"

        def do_nonlocal():
            icke-lokalt skräppost
            spam = "icke-lokalt skräppost"

        def do_global():
            global skräppost
            spam = "global skräppost"

        spam = "test spam"
        do_local()
        print("Efter lokal tilldelning:", spam)
        do_nonlocal()
        print("Efter icke-lokal tilldelning:", spam)
        do_global()
        print("Efter global tilldelning:", spam)

    scope_test()
    print("I global omfattning:", spam)

Utmatningen av exempelkoden är:

    Efter lokalt uppdrag: test spam
    Efter icke-lokalt uppdrag: icke-lokalt spam
    Efter global tilldelning: icke-lokalt spam
    I global omfattning: global skräppost

Observera att local-tilldelningen (som är standard) inte ändrade scope_test:s bindning av spam. Tilldelningen `nonlocal` ändrade scope_test:s bindning av spam, och tilldelningen `global` ändrade bindningen på modulnivå.

Du kan också se att det inte fanns någon tidigare bindning för spam före tilldelningen `global`.

## 9.3. En första titt på klasserna

Classes introducerar lite ny syntax, tre nya objekttyper och en del ny semantik.

### 9.3.1. Syntax för klassdefinition

Den enklaste formen av klassdefinition ser ut så här:

    class ClassName:
        <statement-1>
        .
        .
        .
        <statement-N>

Klassdefinitioner måste, precis som funktionsdefinitioner (`def`-satser), exekveras innan de får någon effekt. (Man skulle kunna tänka sig att placera en klassdefinition i en gren av en `if`-sats, eller inuti en funktion)

I praktiken är satserna i en klassdefinition oftast funktionsdefinitioner, men andra satser är tillåtna och ibland användbara — vi återkommer till detta senare. Funktionsdefinitionerna i en klass har normalt en speciell form av argumentlista, dikterad av anropskonventionerna för metoder — återigen, detta förklaras senare.

När en klassdefinition skrivs in skapas ett nytt namnrymd som används som det lokala området — alla tilldelningar till lokala variabler går alltså till detta nya namnrymd. I synnerhet funktionsdefinitioner binder namnet på den nya funktionen här.

När en klassdefinition lämnas på normalt sätt (via slutet) skapas ett klassobjekt. Detta är i princip ett omslag runt innehållet i det namnrymd som skapats av klassdefinitionen; vi lär oss mer om klassobjekt i nästa avsnitt. Det ursprungliga lokala omfånget (det som gällde precis innan klassdefinitionen skrevs in) återställs och klassobjektet binds här till det klassnamn som anges i klassdefinitionens rubrik (`ClassName` i exemplet).

### 9.3.2. Klassobjekt

Klassobjekt stöder två typer av operationer: attributreferenser och instansiering.

Attributreferenser använder den standardsyntax som används för alla attributreferenser i Python: `obj.name`. Giltiga attributnamn är alla de namn som fanns i klassens namnrymd när klassobjektet skapades. Så, om klassdefinitionen såg ut så här:

    class MyClass:
        """A simple example class"""
        i = 12345

        def f(self):
            return 'hello world'

så är `MyClass.i` och `MyClass.f` giltiga attributreferenser, som returnerar ett heltal respektive ett funktionsobjekt. Klassattribut kan också tilldelas, så du kan ändra värdet på `MyClass.i` genom tilldelning. `__doc__` är också ett giltigt attribut, som returnerar den dokumentsträng som tillhör klassen: `"A simple example class"`.

Klass instantiering använder funktionsnotation. Låtsas bara att klassobjektet är en parameterlös funktion som returnerar en ny instans av klassen. Till exempel (med antagande av ovanstående klass):

    x = MyClass()

skapar en ny instans av klassen och tilldelar detta objekt till den lokala variabeln `x`.

Instantiering (”anrop” av ett klassobjekt) skapar ett tomt objekt. Många klasser vill skapa objekt med instanser som är anpassade till ett visst initialt tillstånd. Därför kan en klass definiera en speciell metod med namnet `__init__()`, så här:

    def __init__(self):
        self.data = []

När en klass definierar en `__init__()`-metod, anropar klassinstantiering automatiskt `__init__()` för den nyskapade klassinstansen. Så i det här exemplet kan en ny, initialiserad instans erhållas genom att:

    x = MyClass()

Naturligtvis kan metoden `__init__()` ha argument för större flexibilitet. I så fall skickas de argument som ges till operatorn för klassinstantiering vidare till `__init__()`. Till exempel

    >>> class Complex:
    ...     def __init__(self, realpart, imagpart):
    ...         self.r = realpart
    ...         self.i = imagpart
    ...
    >>> x = Complex(3.0, -4.5)
    >>> x.r, x.i
    (3.0, -4.5)

### 9.3.3. Instansobjekt

Vad kan vi nu göra med instansobjekt? De enda operationer som förstås av instansobjekt är attributreferenser. Det finns två typer av giltiga attributnamn: dataattribut och metoder.

Dataattribut motsvarar ”instansvariabler” i Smalltalk och ”datamedlemmar” i C++. Dataattribut behöver inte deklareras; precis som lokala variabler uppstår de när de först tilldelas. Om till exempel `x` är instansen av `MyClass` som skapades ovan, kommer följande kod att skriva ut värdet `16`, utan att lämna några spår:

    x.counter = 1
    medan x.counter < 10:
        x.räknare = x.räknare * 2
    print(x.räknare)
    radera x.räknare

Den andra typen av instansattributreferens är en metod. En metod är en funktion som ”hör till” ett objekt.

Giltiga metodnamn för ett instansobjekt beror på dess klass. Per definition definierar alla attribut för en klass som är funktionsobjekt motsvarande metoder för dess instanser. Så i vårt exempel är `x.f` en giltig metodreferens, eftersom `MyClass.f` är en funktion, men `x.i` är det inte, eftersom `MyClass.i` inte är det. Men `x.f` är inte samma sak som `MyClass.f` — det är ett metodobjekt, inte ett funktionsobjekt.

### 9.3.4. Metod Objekt

Vanligtvis anropas en metod direkt efter att den har bundits:

    x.f()

Om `x = MyClass()`, som ovan, returnerar detta strängen `'hello world'`. Det är dock inte nödvändigt att anropa en metod direkt: `x.f` är ett metodobjekt och kan sparas och anropas senare. Till exempel:

    xf = x.f
    while True:
        print(xf())

kommer att fortsätta att skriva ut ”Hello World” till tidens ände.

Vad händer egentligen när en metod anropas? Du kanske har lagt märke till att `x.f()` anropades utan argument ovan, trots att funktionsdefinitionen för `f()` angav ett argument. Vad hände med argumentet? Python gör väl ett undantag när en funktion som kräver ett argument anropas utan något — även om argumentet faktiskt inte används…

Egentligen har du kanske gissat svaret: det speciella med metoder är att instansobjektet skickas som funktionens första argument. I vårt exempel är anropet `x.f()` exakt likvärdigt med `MyClass.f(x)`. I allmänhet är anrop av en metod med en lista med n argument likvärdigt med anrop av motsvarande funktion med en argumentlista som skapas genom att infoga metodens instansobjekt före det första argumentet.

I allmänhet fungerar metoder på följande sätt. När ett icke-dataattribut för en instans refereras, söks instansens klass. Om namnet anger ett giltigt klassattribut som är ett funktionsobjekt, packas referenser till både instansobjektet och funktionsobjektet in i ett metodobjekt. När metodobjektet anropas med en argumentlista, konstrueras en ny argumentlista av instansobjektet och argumentlistan, och funktionsobjektet anropas med denna nya argumentlista.

### 9.3.5. Klass- och instansvariabler

Generellt sett är instansvariabler för data som är unika för varje instans och klassvariabler för attribut och metoder som delas av alla instanser av klassen:

    class Dog:

        kind = 'canine'         # class variable shared by all instances

        def __init__(self, name):
            self.name = name    # instance variable unique to each instance

    >>> d = Dog('Fido')
    >>> e = Dog('Buddy')
    >>> d.kind                  # shared by all dogs
    'canine'
    >>> e.kind                  # shared by all dogs
    'canine'
    >>> d.name                  # unique to d
    'Fido'
    >>> e.name                  # unique to e
    'Buddy'

As discussed in Några ord om namn och objekt, shared data can have possibly surprising effects involving mutable objects such as lists and dictionaries. For example, the tricks list in the following code should not be used as a class variable because just a single list would be shared by all Dog instances:

    class Dog:

        tricks = []             # mistaken use of a class variable

        def __init__(self, name):
            self.name = name

        def add_trick(self, trick):
            self.tricks.append(trick)

    >>> d = Dog('Fido')
    >>> e = Dog('Buddy')
    >>> d.add_trick('roll over')
    >>> e.add_trick('play dead')
    >>> d.tricks                # unexpectedly shared by all dogs
    ['roll over', 'play dead']

Korrekt design av klassen bör använda en instansvariabel istället:

    class Dog:

        def __init__(self, name):
            self.name = name
            self.tricks = []    # creates a new empty list for each dog

        def add_trick(self, trick):
            self.tricks.append(trick)

    >>> d = Dog('Fido')
    >>> e = Dog('Buddy')
    >>> d.add_trick('roll over')
    >>> e.add_trick('play dead')
    >>> d.tricks
    ['roll over']
    >>> e.tricks
    ['play dead']

## 9.4. Slumpmässiga kommentarer

Om samma attributnamn förekommer både i en instans och i en klass, prioriterar attributuppslagningen instansen:

    >>> class Warehouse:
    ...    purpose = 'storage'
    ...    region = 'west'
    ...
    >>> w1 = Warehouse()
    >>> print(w1.purpose, w1.region)
    storage west
    >>> w2 = Warehouse()
    >>> w2.region = 'east'
    >>> print(w2.purpose, w2.region)
    storage east

Dataattribut kan refereras till av metoder såväl som av vanliga användare (”klienter”) av ett objekt. Med andra ord är klasser inte användbara för att implementera rena abstrakta datatyper. Faktum är att ingenting i Python gör det möjligt att genomdriva datahölje — allt är baserat på konvention. (Å andra sidan kan Python-implementationen, skriven i C, helt dölja implementationsdetaljer och kontrollera åtkomst till ett objekt om det behövs; detta kan användas av tillägg till Python skrivna i C.)

Klienter bör använda dataattribut med försiktighet — klienter kan förstöra invarianter som upprätthålls av metoderna genom att stämpla på sina dataattribut. Observera att klienter kan lägga till egna dataattribut till ett instansobjekt utan att påverka metodernas giltighet, så länge namnkonflikter undviks — återigen kan en namngivningskonvention spara mycket huvudvärk här.

Det finns ingen förkortning för att referera till dataattribut (eller andra metoder!) inom metoder. Jag tycker att detta faktiskt ökar metodernas läsbarhet: det finns ingen risk för att man blandar ihop lokala variabler och instansvariabler när man tittar igenom en metod.

Ofta kallas det första argumentet i en metod för `self`. Detta är inget annat än en konvention: namnet `self` har absolut ingen speciell betydelse för Python. Observera dock att om du inte följer konventionen kan din kod vara mindre läsbar för andra Python-programmerare, och det är också tänkbart att ett class browser-program kan skrivas som förlitar sig på en sådan konvention.

Varje funktionsobjekt som är ett klassattribut definierar en metod för instanser av den klassen. Det är inte nödvändigt att funktionsdefinitionen är textuellt innesluten i klassdefinitionen: att tilldela ett funktionsobjekt till en lokal variabel i klassen är också ok. Till exempel:

    # Function defined outside the class
    def f1(self, x, y):
        return min(x, x+y)

    class C:
        f = f1

        def g(self):
            return 'hello world'

        h = g

Nu är `f`, `g` och `h` alla attribut av klassen `C` som refererar till funktionsobjekt, och följaktligen är de alla metoder för instanser av `C` — `h` är exakt ekvivalent med `g`. Notera att denna praxis oftast bara tjänar till att förvirra läsaren av ett program.

Metoder kan anropa andra metoder genom att använda metodattribut för argumentet `self`:

    class Bag:
        def __init__(self):
            self.data = []

        def add(self, x):
            self.data.append(x)

        def addtwice(self, x):
            self.add(x)
            self.add(x)

Metoder kan referera till globala namn på samma sätt som vanliga funktioner. Det globala scope som associeras med en metod är den modul som innehåller dess definition. (En klass används aldrig som globalt scope.) Även om det sällan finns någon bra anledning att använda globala data i en metod, finns det många legitima användningsområden för det globala scopet: För det första kan funktioner och moduler som importeras till det globala scopet användas av metoder, liksom funktioner och klasser som definieras i det. Vanligtvis är klassen som innehåller metoden själv definierad i detta globala scope, och i nästa avsnitt hittar vi några goda skäl till varför en metod skulle vilja referera till sin egen klass.

Varje värde är ett objekt och har därför en klass (även kallad typ). Den lagras som `object.__class__`.

## 9.5. Ärftlighet

Naturligtvis skulle en språkfunktion inte vara värd namnet ”klass” utan att stödja arv. Syntaxen för en härledd klassdefinition ser ut så här:

    class DerivedClassName(BaseClassName):
        <statement-1>
        .
        .
        .
        <statement-N>

Namnet `BaseClassName` måste definieras i en namnrymd som är tillgänglig från det scope som innehåller den härledda klassdefinitionen. I stället för ett basklassnamn är även andra godtyckliga uttryck tillåtna. Detta kan vara användbart t.ex. när basklassen är definierad i en annan modul:

    class DerivedClassName(modname.BaseClassName):

Exekveringen av en härledd klassdefinition sker på samma sätt som för en basklass. När klassobjektet konstrueras kommer basklassen ihåg. Detta används för att lösa attributreferenser: om ett efterfrågat attribut inte finns i klassen, fortsätter sökningen i basklassen. Denna regel tillämpas rekursivt om basklassen i sig själv är härledd från någon annan klass.

Det finns inget speciellt med instansiering av härledda klasser: `DerivedClassName()` skapar en ny instans av klassen. Metodreferenser löses på följande sätt: motsvarande klassattribut söks, vid behov nedåt i kedjan av basklasser, och metodreferensen är giltig om detta ger ett funktionsobjekt.

Härledda klasser kan åsidosätta metoder i sina basklasser. Eftersom metoder inte har några speciella privilegier när de anropar andra metoder i samma objekt, kan en metod i en basklass som anropar en annan metod som definieras i samma basklass sluta med att anropa en metod i en härledd klass som åsidosätter den. (För C++-programmerare: alla metoder i Python är i praktiken `virtual`)

En överordnad metod i en härledd klass kan i själva verket vilja utvidga snarare än att bara ersätta basklassens metod med samma namn. Det finns ett enkelt sätt att anropa basklassmetoden direkt: bara anropa `BaseClassName.methodname(self, arguments)`. Detta är ibland användbart för klienter också. (Observera att detta endast fungerar om basklassen är tillgänglig som `BaseClassName` i det globala omfånget)

Python har två inbyggda funktioner som arbetar med nedärvning:

- Använd `isinstance()` för att kontrollera en instants typ: `isinstance(obj, int)` kommer att vara `True` endast om `obj.__class__` är `int` eller någon klass härledd från `int`.

- Använd `issubclass()` för att kontrollera klassens arv: `issubclass(bool, int)` är `True` eftersom `bool` är en subklass av `int`. Men `issubclass(float, int)` är `False` eftersom `float` inte är en subklass av `int`.

### 9.5.1. Multipel nedärvning

Python stöder också en form av multipel nedärvning. En klassdefinition med flera basklasser ser ut så här:

    class DerivedClassName(Base1, Base2, Base3):
        <statement-1>
        .
        .
        .
        <statement-N>

För de flesta ändamål och i de enklaste fallen kan du tänka dig att sökningen efter attribut som ärvs från en överordnad klass sker med djupet först, från vänster till höger, och inte två gånger i samma klass där det finns en överlappning i hierarkin. Om ett attribut inte hittas i `DerivedClassName`, söks det alltså i `Base1`, sedan (rekursivt) i basklasserna i `Base1`, och om det inte hittas där, söks det i `Base2`, och så vidare.

I själva verket är det något mer komplext än så; metodresolutionsordningen ändras dynamiskt för att stödja kooperativa anrop till `super()`. Detta tillvägagångssätt är känt i vissa andra språk med flera arv som call-next-method och är kraftfullare än superanropet som finns i språk med enstaka arv.

Dynamisk ordning är nödvändig eftersom alla fall av multipel nedärvning uppvisar en eller flera diamantrelationer (där minst en av de överordnade klasserna kan nås via flera vägar från den underordnade klassen). Till exempel ärver alla klasser från `object`, så alla fall av multipel nedärvning ger mer än en väg för att nå `object`. För att förhindra att basklasserna anropas mer än en gång linjäriserar den dynamiska algoritmen sökordningen på ett sätt som bevarar den vänster-till-höger-ordning som anges i varje klass, som bara anropar varje överordnad klass en gång och som är monoton (vilket innebär att en klass kan underordnas utan att det påverkar rangordningen för dess överordnade klasser). Sammantaget gör dessa egenskaper det möjligt att utforma tillförlitliga och utbyggbara klasser med multipel arvbarhet. För mer detaljer, se The Python 2.3 Method Resolution Order.

## 9.6. Privata variabler

”Privata” instansvariabler som inte kan nås annat än från insidan av ett objekt finns inte i Python. Det finns dock en konvention som följs av de flesta Python-koder: ett namn som inleds med ett understreck (t.ex. `_spam`) ska behandlas som en icke-publik del av API:et (oavsett om det är en funktion, en metod eller en datamedlem). Det bör betraktas som en implementeringsdetalj och kan ändras utan föregående meddelande.

Eftersom det finns ett giltigt användningsområde för klassprivata medlemmar (nämligen att undvika namnkrockar mellan namn och namn som definieras av underklasser), finns det begränsat stöd för en sådan mekanism, kallad name mangling. Varje identifierare av formen `__spam` (minst två inledande understrykningar, högst en efterföljande understrykning) ersätts textuellt med `_classname__spam`, där `classname` är det aktuella klassnamnet med inledande understrykning(ar) borttagna. Denna mangling görs utan hänsyn till identifierarens syntaktiska position, så länge den förekommer inom definitionen av en klass.

Se även

Specifikationerna för privat namnmangling för detaljer och specialfall.

Namnmangling är användbart för att låta underklasser åsidosätta metoder utan att bryta metodanrop inom klassen. Till exempel:

    class Mapping:
        def __init__(self, iterable):
            self.items_list = []
            self.__update(iterable)

        def update(self, iterable):
            for item in iterable:
                self.items_list.append(item)

        __update = update   # private copy of original update() method

    class MappingSubclass(Mapping):

        def update(self, keys, values):
            # provides new signature for update()
            # but does not break __init__()
            for item in zip(keys, values):
                self.items_list.append(item)

Exemplet ovan skulle fungera även om `MappingSubclass` skulle införa en `__update` identifierare eftersom den ersätts med `_Mapping__update` i klassen `Mapping` respektive `_MappingSubclass__update` i klassen `MappingSubclass`.

Observera att mangling-reglerna främst är utformade för att undvika olyckor; det är fortfarande möjligt att komma åt eller ändra en variabel som anses vara privat. Detta kan till och med vara användbart under speciella omständigheter, t.ex. i felsökaren.

Observera att kod som skickas till `exec()` eller `eval()` inte betraktar namnet på den anropande klassen som den aktuella klassen; detta liknar effekten av `global`-satsen, vars effekt också är begränsad till kod som är byte-kompilerad tillsammans. Samma begränsning gäller för `getattr()`, `setattr()` och `delattr()`, samt när man refererar direkt till `__dict__`.

## 9.7. Lite av varje

Ibland är det användbart att ha en datatyp som liknar Pascals ”record” eller C:s ”struct”, som samlar ihop några namngivna dataobjekt. Det idiomatiska tillvägagångssättet är att använda `dataclasses` för detta ändamål:

    from dataclasses import dataclass

    @dataclass
    class Employee:
        name: str
        dept: str
        salary: int

    >>> john = Employee('john', 'computer lab', 1000)
    >>> john.dept
    'computer lab'
    >>> john.salary
    1000

En del av Python-koden som förväntar sig en viss abstrakt datatyp kan ofta skickas till en klass som emulerar metoderna för den datatypen istället. Om du till exempel har en funktion som formaterar data från ett filobjekt kan du definiera en klass med metoderna `read()` och `readline()` som hämtar data från en strängbuffert istället, och skicka den som argument.

Instansmetodobjekt har också attribut: `m.__self__` är instansobjektet med metoden `m()`, och `m.__func__` är funktionsobjektet som motsvarar metoden.

## 9.8. Iteratorer

Vid det här laget har du säkert märkt att de flesta containerobjekt kan loopas över med hjälp av en `for`-sats:

    för element i [1, 2, 3]:
        print(element)
    för element i (1, 2, 3):
        print(element)
    for key in {'ett':1, 'två':2}:
        print(nyckel)
    för char i "123":
        print(char)
    for line in open("minfil.txt"):
        print(rad, end='')

Denna typ av åtkomst är tydlig, kortfattad och bekväm. Användningen av iteratorer genomsyrar och förenar Python. Bakom kulisserna anropar `for`-satsen `iter()` på containerobjektet. Funktionen returnerar ett iteratorobjekt som definierar metoden `__next__()` som öppnar elementen i containern ett i taget. När det inte finns några fler element ger `__next__()` upphov till ett `StopIteration`-undantag som säger till `for`-slingan att avslutas. Du kan anropa metoden `__next__()` med hjälp av den inbyggda funktionen `next()`; detta exempel visar hur det fungerar:

    >>> s = 'abc'
    >>> it = iter(s)
    >>> it
    <str_iterator object at 0x10c90e650>
    >>> next(it)
    'a'
    >>> next(it)
    'b'
    >>> next(it)
    'c'
    >>> next(it)
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
        next(it)
    StopIteration

Efter att ha sett mekaniken bakom iteratorprotokollet är det enkelt att lägga till iteratorbeteende i dina klasser. Definiera en `__iter__()`-metod som returnerar ett objekt med en `__next__()`-metod. Om klassen definierar `__next__()`, så kan `__iter__()` bara returnera `self`:

    class Reverse:
        """Iterator for looping over a sequence backwards."""
        def __init__(self, data):
            self.data = data
            self.index = len(data)

        def __iter__(self):
            return self

        def __next__(self):
            if self.index == 0:
                raise StopIteration
            self.index = self.index - 1
            return self.data[self.index]

    >>> rev = Reverse('spam')
    >>> iter(rev)
    <__main__.Reverse object at 0x00A1DB50>
    >>> for char in rev:
    ...     print(char)
    ...
    m
    a
    p
    s

## 9.9. Generatorer

Generators är ett enkelt och kraftfullt verktyg för att skapa iteratorer. De skrivs som vanliga funktioner men använder `yield`-satsen när de vill returnera data. Varje gång `next()` anropas fortsätter generatorn där den slutade (den kommer ihåg alla datavärden och vilket uttalande som senast kördes). Ett exempel visar att generatorer kan vara trivialt enkla att skapa:

    def reverse(data):
        för index i intervall(len(data)-1, -1, -1):
            avkastning data[index]

    >>> for char in reverse('golf'):
    ...     print(char)
    ...
    f
    l
    o
    g

Allt som kan göras med generatorer kan också göras med klassbaserade iteratorer enligt beskrivningen i föregående avsnitt. Det som gör generatorer så kompakta är att metoderna `__iter__()` och `__next__()` skapas automatiskt.

En annan viktig egenskap är att de lokala variablerna och exekveringstillståndet sparas automatiskt mellan anropen. Detta gjorde funktionen enklare att skriva och mycket tydligare än ett tillvägagångssätt som använder instansvariabler som `self.index` och `self.data`.

Förutom automatiskt skapande av metoder och sparande av programstatus ger generatorer automatiskt upphov till `StopIteration` när de avslutas. I kombination gör dessa funktioner det enkelt att skapa iteratorer utan större ansträngning än att skriva en vanlig funktion.

## 9.10. Generatoruttryck

Vissa enkla generatorer kan kodas kortfattat som uttryck med en syntax som liknar listförståelser men med parenteser istället för hakparenteser. Dessa uttryck är utformade för situationer där generatorn används direkt av en omslutande funktion. Generatoruttryck är mer kompakta men mindre mångsidiga än fullständiga generatordefinitioner och tenderar att vara mer minnesvänliga än motsvarande listkomprehensioner.

Exempel:

    >>> sum(i*i for i in range(10))                 # sum of squares
    285

    >>> xvec = [10, 20, 30]
    >>> yvec = [7, 5, 3]
    >>> sum(x*y for x,y in zip(xvec, yvec))         # dot product
    260

    >>> unique_words = set(word for line in page  for word in line.split())

    >>> valedictorian = max((student.gpa, student.name) for student in graduates)

    >>> data = 'golf'
    >>> list(data[i] for i in range(len(data)-1, -1, -1))
    ['f', 'l', 'o', 'g']

Fotnoter

[ 1 ]

Med undantag för en sak. Modulobjekt har ett hemligt skrivskyddat attribut som heter `__dict__` som returnerar den ordbok som används för att implementera modulens namnrymd; namnet `__dict__` är ett attribut men inte ett globalt namn. Att använda detta bryter naturligtvis mot abstraktionen i implementeringen av namnrymden och bör begränsas till saker som debuggar efter avslutat arbete.