När en räknare ska öka eller en lista fyllas på syns ofta += i Python-koden. Vanligen uppdaterar operatorn värdet på vänster sida, men om det ursprungliga objektet ändras på plats beror på vilken typ det är.

+= lägger till ett värde, men beteendet beror på typen
- Tal:
count += 1ökar talet och binder variabeln till det nya värdet. - Listor: operatorn kan ändra listan på plats, så andra namn för samma lista ser också ändringen.
- Tupler: tuplen är oföränderlig, men ett objekt inuti den kan ändå ändras.
- Funktioner:
+=är en sats, inte ett uttryck som kan användas direkt som argument.
+= är mer än en kortare skrivning av +
För ett heltal är skillnaden lätt att missa: count += 1 ger samma värde som count = count + 1. Men Python behandlar augmented assignment som en egen operation, och uttrycken kan få olika effekt när vänsterledet är ett föränderligt objekt. Det är typen, inte bara symbolen, som styr vad som händer.
count = 4
count += 1
print(count) # 5En annan praktisk skillnad är att vänsterledet bara utvärderas en gång. I uttrycket items[index()] += 1 anropas alltså index() en gång, vilket kan spela roll om funktionen har sidoeffekter. Python beskriver reglerna i språkreferensen för enkla satser.
Jag tycker att den säkraste tumregeln är att använda += när du vill uppdatera ett befintligt värde, men kontrollera om andra namn kan peka på samma föränderliga objekt. Det är i listor som den skillnaden brukar bli synlig.
Med listor kan += ändra värdet bakom flera variabelnamn
Två variabelnamn kan hänvisa till samma lista. Om listan sedan uppdateras på plats ser båda namnen den nya innehållet, vilket kan överraska när en funktion eller en annan del av programmet delar referensen. Det är objektet som ändras, inte bara namnet.
first = [" startsida"]
second = first
first += [" om oss"]
print(first) # [' startsida', ' om oss']
print(second) # [' startsida', ' om oss']Jämför med tilldelning efter vanlig addition. Då skapas en ny lista för first, medan second fortfarande pekar på den gamla. Den här skillnaden är användbar när du vill undvika att ändra en lista som delas med annan kod.
| Situation | Vad händer | Vad du kan göra |
|---|---|---|
| Flera namn pekar på samma lista | += kan ändra listan så att alla namn ser ändringen. |
Använd first = first + extra eller skapa en kopia om den delade listan ska lämnas orörd. |
| Du vill lägga flera element sist i en lista | += lägger till elementen från högerledets itererbara objekt. |
Använd exempelvis items += ["kontakt", "blogg"]. |
| Du vill lägga till en enda lista som ett element | += lägger till innehållets element, inte listan som ett enda nästlat element. |
Använd items.append(other) om hela listan ska bli ett element. |
Den sista skillnaden går lätt att blanda ihop med append(). items += ["kontakt"] lägger till strängen som ett element, medan items.append(["kontakt"]) lägger till en lista som innehåller strängen.
En tupel kan ge TypeError trots att listan inuti ändras
En tupel går inte att ändra genom att byta ut ett av sina element. Men om ett element är en lista kan själva listan fortfarande ändras. Det kan ge ett märkligt resultat: ett +=-uttryck kan ändra listan och sedan ändå leda till ett TypeError.
box = (["utkast"],)
box[0] += ["publicerad"]Här lägger listans egen +=-operation till texten, men Python försöker därefter skriva tillbaka resultatet på tupelens plats. Det sista steget misslyckas eftersom tuplen inte tillåter elementtilldelning. Listan kan alltså hinna ändras innan felet uppstår.
Python tar upp just den här sortens skillnad i sin programmerings-FAQ. Om du vill ändra listan utan att försöka skriva tillbaka till tupeln kan du anropa en metod direkt:
box[0].extend(["publicerad"])
print(box) # (['utkast', 'publicerad'],)Det är en bra påminnelse om att muterbarhet sitter i objekten, inte i behållaren som råkar innehålla dem. En tupel skyddar sin egen struktur, men gör inte automatiskt innehållet oföränderligt.
Strängar och egna klasser följer andra regler
Strängar är oföränderliga, så text += " mer" skapar ett nytt strängvärde och binder variabeln till det. För en kort etikett eller ett litet meddelande är det lättläst. Om många delar ska fogas ihop i en loop blir en lista med bitar och "".join(parts) ofta ett bättre upplägg.
För egna klasser kan += anpassas med specialmetoden __iadd__. Om den inte finns kan Python falla tillbaka på vanlig addition med __add__, så beteendet beror på hur klassen implementerar operatorerna. PEP 203 beskriver den historiska modellen bakom augmented assignment och metoderna för sådana operatorer.
Det innebär att en klass inte automatiskt blir effektivare eller muterbar bara för att den används med +=. Kontrollera klassens dokumentation om det spelar roll om objektet ändras på plats, särskilt när flera variabler kan hänvisa till samma instans.
Välj operator efter vilken effekt du vill ha
Om du bara räknar uppåt med ett heltal är += ett smidigt och tydligt val. När vänsterledet är en lista eller ett eget objekt bör beslutet i stället följa vad du vill ska hända med eventuella delade referenser.
- Uppdatera en räknare: använd
count += 1. - Ändra en delad lista: använd
+=om alla som hänvisar till listan ska se ändringen. - Behåll den gamla listan: skapa en ny med
items = items + more. - Bygg en lång text i flera steg: samla delarna och slå ihop dem med
join().
När ett oväntat resultat dyker upp, börja med att kontrollera typen på vänster sida och om någon annan variabel pekar på samma objekt. Ofta räcker de två kontrollerna för att förstå varför += gjorde mer, eller mindre, än väntat.