2016-08-21 6 views
11

Ich spielte gerade im Interpreter herum und stieß auf etwas, das ich nicht verstehe. Wenn ich ein Tupel mit einer Liste als eines der Elemente erstelle und dann versuche, diese Liste zu aktualisieren, passiert etwas Seltsames. Zum Beispiel, wenn ich laufe dies:Aktualisieren einer Liste innerhalb eines Tupels

tup = (1,2,3,[4,5]) 
tup[3] += [6] 

ich:

TypeError: 'tuple' object does not support item assignment 

das ist genau das, was ich erwartet hatte. Jedoch dann, wenn ich die Tupel wieder verweisen, die ich erhalten:

>>> tup 
(1, 2, 3, [4, 5, 6]) 

So ist die Liste in der Tat aktualisiert wurde, obwohl Python eine Ausnahme ausgelöst hat. Wie funktioniert das? Ich kann mir ein Szenario nicht vorstellen, in dem ich eigentlich so etwas tun möchte, aber ich würde trotzdem gerne verstehen, was vor sich geht. Vielen Dank.

Antwort

27

Dies ist tatsächlich in der Python docs dokumentiert.

BEARBEITEN: Hier ist eine Zusammenfassung, so dass dies eine vollständigere Antwort ist.

  1. Wenn wir += verwenden, Python ruft die __iadd__ magische Methode auf den Punkt, dann wird der Rückgabewert in der nachfolgenden Artikel Zuordnung.
  2. Für Listen entspricht __iadd__ dem Aufruf extend auf der Liste und dann die Liste zurückgeben.
  3. Wenn wir also tup[3] += [6] nennen, ist es gleichbedeutend mit:

    result = tup[3].__iadd__([6]) 
    tup[3] = result 
    
  4. Von # 2, wir dies ist äquivalent bestimmen kann:

    result = tup[3].extend([6]) 
    tup[3] = result 
    
  5. Die erste Zeile gelingt extend in Berufung auf der Liste und da die Liste veränderbar ist, wird sie aktualisiert. Die nachfolgende Zuweisung schlägt jedoch fehl, da Tupel unveränderlich sind und den Fehler auslösen.
+2

Ich denke, die Antwort würde von der Ergänzung profitieren, dass es ist, weil die Erweiterung nicht nur ist 'tup [3] .__ iadd __ ([6]) '; es ist 'tup [3] = tup [3] .__ iadd __ ([6])'. Es ist nur praktisch, dass 'list .__ iadd__' das gleiche Objekt zurückgibt, das es mutiert. – zondo

+0

Danke für den Link zur Dokumentation! Das ist eine große Hilfe. –

+0

Danke, ich habe das in der Dokumentation nicht verstanden. Um sicherzustellen, dass ich das richtig verstehe, wird die Liste im Grunde in meinem Beispiel aktualisiert, weil ich gerade tup [3] .__ iadd __ ([6]) und THEN versucht (und fehlschlägt) die Item-Zuweisung auf dem Tupel? Also bekomme ich die Ausnahme, dass es fehlgeschlagen ist, aber zu diesem Zeitpunkt haben wir die Liste bereits aktualisiert? –

Verwandte Themen