2013-02-11 6 views
10

Wenn Sie eine for Schleife in Python verwenden, um über Elemente in einer Liste zu iterieren, ändert sich item (unten) das entsprechende Element in items?Funktionieren Python for-Schleifen als Referenz?

for item in items: 
    item += 1 

Wird jedes Element in Elementen inkrementiert oder bleibt dasselbe wie vor der Schleife?

[Anmerkung: Ich würde in Python 2.7 und 3.x interessieren]

+5

Warum versuchst du es nicht einfach? –

+0

Nein; macht das [vorherige Antwort von mir] (http://stackoverflow.com/questions/12080552/python-list-doesnt-reflect-variable-change-new-to-python/12080644#12080644) überhaupt Hilfe? –

+0

Ich denke nicht, dass es den Wert chagen wird (konntest du es nicht versuchen?) –

Antwort

12

Nein, Variablen in Python sind nicht Zeiger.

Sie verweisen stattdessen auf Objekte auf einem Heap, und das Zuweisen zu einer Variablen ändert nicht das referenzierte Objekt, sondern die Variable. Variablen und Objekte sind wie Labels, die an Ballons gebunden sind. Die Zuweisung verschiebt das Label stattdessen an einen anderen Ballon.

Sehen Sie diese previous answer of mine, um diese Idee von Ballons und Labels ein wenig mehr zu erkunden.

Das heißt, einige Objekte Typen implementieren spezifische In-Place-Addition Verhalten. Wenn das Objekt veränderbar ist (der Ballon selbst kann sich ändern), dann kann ein in-place add könnte als eine Mutation statt einer Zuordnung interpretiert werden.

Also, für ganze Zahlen, item += 1 ist wirklich das gleiche wie item = item + 1, weil ganze Zahlen unveränderlich sind. Sie haben, um ein neues ganzzahliges Objekt zu erstellen und das item-Label an das neue Objekt zu binden.

Listen auf der anderen Seite, sind wandelbar und lst += [other, items] als lst.__iadd__([other, items]) umgesetzt und das verändert den lst Ballon selbst. Eine Zuweisung findet noch statt, aber es ist eine Neuzuweisung des gleichen Objekts, da die .__iadd__() Methode self anstelle eines neuen Objekts einfach zurückgibt. Am Ende binden wir das Etikett an den gleichen Ballon an.

Die Schleife gibt Ihnen einfach einen Verweis auf das nächste Element in der Liste bei jeder Iteration. Sie können nicht die ursprüngliche Liste selbst ändern (das ist nur ein weiterer Satz von Beschriftungstexten); Stattdessen erhalten Sie für jedes enthaltene Element ein neues Etikett.

+1

Insbesondere ist es nicht eine Mutation gefolgt von einer Zuweisung ? Sie mutieren das Objekt in einer Funktion und dann machen Sie eine Zuweisung zu dem, was diese Funktion zurückgibt (was * sollte * nur das Objekt selbst sein, muss aber nicht sein)? - Mit anderen Worten, "i + = etwas" ist das gleiche wie "i = i .__ iadd __ (etwas)" – mgilson

+1

@mgilson: Ja, '.__ iadd __()' wird erwartet, in diesem Fall "self" zurückzugeben. –

+0

Ja, zu erwarten, aber es muss nicht. Ich finde es lehrreich, darauf hinzuweisen, da es sehr deutlich erklärt, wie man mit '+ =' mit veränderbaren und unveränderlichen Objekten ein unterschiedliches Verhalten erreichen kann. – mgilson

3

Nun, es hängt wirklich von den Einzelteilen ab.

Nehmen Sie den folgenden Fall:

class test(): 
    pass 

a = test() 
a.value = 1 

b = test() 
b.value = 2 

l = [a,b] 

for item in l: 
    item.value += 1 

for item in l: 
    print item.value 

>>> 
2 
3 

und in diesem Fall:

l2 = [1,2,3] 

for item in l2: 
    item += 1 

for item in l2: 
    print item 

>>> 
1 
2 
3 

So wie Sie sehen können, müssen Sie die Zeiger als Martijn sagte verstehen.

+0

Sie haben Recht, es hängt technisch von den Elementen ab (nämlich von der Definition von "__iadd__"). Aber nicht so, wie du es zeigst: Artikelzuordnung * immer * funktioniert so. Was Sie zeigen, ist, dass die Attributzuweisung von der lokalen Zuweisung verschieden ist, aber das ist eine ganz andere Sache (obwohl verwandt und auch wichtig). -1 – delnan

+2

Dies ist nicht korrekt; Wenn Sie einer lokalen Variablen nicht zuweisen, weisen Sie einem anderen Objekt ein Attribut zu. Das mutiert das veränderbare Objekt, keine lokale Variable. –

+1

Ich behauptete nie etwas anderes, nur zeigen, dass wenn Sie über eine Liste in Python iterieren, Sie in bestimmten Situationen an den Elementen arbeiten können, in anderen Sprachen ist es nicht erlaubt, das Objekt/die Liste zu bearbeiten. –