2016-04-03 10 views
5

Ich bin nicht in der Lage herauszufinden, was hier passiert. Der Verweis auf die Funktion range wird angehängt, um eine rekursive Liste mit dem Index 3 zu erstellen.Welche Bereichsfunktion hat eine Python-Liste?

>>> x = range(3) 
[0, 1, 2] 
>>> x.append(x) 
[0, 1, 2, [...]] 
>>> x[3][3][3][3][0] = 5 
[5, 1, 2, [...]] 

Während, wenn ich versuche, dies:

>>> x = range(3) 
[0, 1, 2] 
>>> x.append(range(3)) 
[0, 1, 2, [0, 1, 2]] 

ich den Grund für den zweiten Fall leicht ableiten kann, aber nicht in der Lage zu verstehen, was Bezug auf range Funktion Anhängen an die Liste angehängt tut.

+3

Warum ist dies beide Python 2 und 3 markiert? 'Bereich' verhält sich in 2 und 3 anders. – interjay

+2

Listen werden als Referenz in Python übergeben. Dies bedeutet, dass Sie im ersten Szenario den Zeiger an x ​​anfügen, nicht den Wert von x. Da x jetzt einen Zeiger auf x enthält, ruft es sich an diesem Punkt rekursiv auf. –

+0

@JacobH: Wenn man sagt "Listen werden per Referenz übergeben", scheint es, als würden sich Listen anders verhalten als andere Objekte. Alle Objekte werden auf die gleiche Weise übergeben (obwohl Leute darüber streiten, was die richtige Formulierung ist). – DSM

Antwort

9

In python2 sind range s list s.

list s, und die meisten Dinge in Python sind Objekte mit Identitäten.

li = [0,1] 
li[1] = li # [0, [...]] 
       # ^----v 
id(li)  # 2146307756 
id(li[1])  # 2146307756 

Da Sie die Liste innerhalb selbst setzen sind, sind erstellen Sie eine rekursive Datenstruktur.

+4

Bitte beachten Sie, dass dies Python 2-spezifisch ist. Bereiche sind in Python 3 völlig unterschiedlich. Zurückgeben eines lazy-evaluierten "Bereich" -Objekts, überhaupt keine Liste. – MattDMo

+0

@Karoly danke für die Antwort, aber ich bin nicht in der Lage zu verstehen, warum die Wertzuweisung von 5 funktioniert. Was ich gelernt habe ist, dass wenn ich ein [1 ] [0] = 5, dann bedeutet es, 5 bis 0 Index an der Liste der Liste bei Index 1 zuzuweisen. – Rahul

+0

Wenn du mein Beispiel meinst: 'li [1]' ist 'li', also ist es einfach' li [0] = 5'. –

0

Zuerst ist das seltsam, und Sie sollten dies wahrscheinlich nicht in der Praxis verwenden. Das Problem ist nicht spezifisch für range Funktion und hat mit Referenzen zu tun. Wenn Sie x.append(x) anrufen, sagen Sie im Wesentlichen, dass x[-1] is x. Also, wenn Sie x[0] ändern, können Sie auch ändern x[-1][0], x[-1][-1][0] usw.

Um zu sehen, dass dies nicht reichen spezifische, könnten Sie copy.copy verwenden:

from copy import copy 

x = range(1) 
x.append(x) # here x[1] is reference to x itself (same object) 
print(x[0], x[1][0], x[1][1][0]) 
x[0] = 1 
print(x[0], x[1][0], x[1][1][0]) # all values change 

# 

x = range(1) 
x.append(copy(x)) # x[1] is a copy of x at previous state (new object) 
print(x[0], x[1][0]) # cannot call x[1][1][0] -> x[1][1] is an int 
x[0] = 1 
print(x[0], x[1][0]) # only the first value changes 

Ausgang:

(0, 0, 0) 
(1, 1, 1) 
(0, 0) 
(1, 0) 
Verwandte Themen