ein veränderbarer Typ innerhalb eines unveränderlichen Containers

8

Ich bin ein wenig verwirrt darüber, Tupelmitglieder zu modifizieren. Folgendes funktioniert nicht:

%Vor%

Aber das funktioniert:

%Vor%

Funktioniert auch:

%Vor%

Funktioniert nicht und funktioniert (hm?!):

%Vor%

Scheinbar gleichbedeutend mit vorherigem, funktioniert aber:

%Vor%

Was genau sind die Regeln des Spiels, wenn du etwas in einem Tupel verändern kannst? Es scheint eher so zu sein, dass die Verwendung des Zuweisungsoperators für Tupelmitglieder verboten ist, aber die letzten beiden Fälle verwirren mich.

    
wim 07.02.2012, 07:06
quelle

3 Antworten

7

Sie können einen änderbaren Wert in einem Tupel immer ändern . Das rätselhafte Verhalten, das Sie mit

sehen %Vor%

wird verursacht durch += . Der Operator += führt eine direkte Hinzufügung durch, aber auch eine Zuweisung - die direkte Hinzufügung funktioniert nur als Datei, aber die Zuweisung schlägt fehl, da das Tupel unveränderlich ist. Denk daran wie

%Vor%

erklärt das besser. Wir können das Modul dis aus der Standardbibliothek verwenden, um den aus beiden Ausdrücken erzeugten Bytecode zu betrachten. Mit += erhalten wir einen INPLACE_ADD bytecode:

%Vor%

Mit + erhalten wir BINARY_ADD :

%Vor%

Beachten Sie, dass wir in beiden Bereichen STORE_FAST erhalten. Das ist der Bytecode, der fehlschlägt, wenn Sie versuchen, in ein Tupel zu speichern - das INPLACE_ADD , das kurz davor kommt, funktioniert einwandfrei.

Dies erklärt, warum der Fall "Arbeitet nicht, und funktioniert" die modifizierte Liste zurücklässt: Das Tupel hat bereits einen Verweis auf die Liste:

%Vor%

Die Liste wird dann von INPLACE_ADD und STORE_FAST fehlgeschlagen:

geändert %Vor%

Das Tupel hat also immer noch einen Verweis auf die gleiche Liste, aber die Liste wurde direkt geändert:

%Vor%     
Martin Geisler 07.02.2012, 07:13
quelle
2

Sie können das Tupel nicht ändern, aber Sie können den Inhalt von Dingen ändern, die im Tupel enthalten sind. Listen (zusammen mit Sätzen, Dicts und Objekten) sind ein Referenztyp und somit ist das "Ding" in das Tupel nur eine Referenz - die tatsächliche Liste ist ein veränderbares Objekt auf die diese Referenz verweist und die geändert werden kann, ohne die Referenz selbst zu ändern.

%Vor%

Nach thing[0][0] = 'b' :

%Vor%

Nach thing[0].append('c') :

%Vor%

Der Grund warum += Fehler ist, dass es nicht vollständig äquivalent zu .append() ist - es führt tatsächlich eine Addition und dann eine Zuweisung durch (und die Zuweisung schlägt fehl), anstatt nur direkt anzufügen.

    
Amber 07.02.2012 07:09
quelle
1

Sie können ein Element eines Tupels nicht ersetzen, aber Sie können den gesamten Inhalt des Elements ersetzen. Das wird funktionieren:

%Vor%     
Lawrence D'Oliveiro 07.02.2012 11:07
quelle