2016-04-03 16 views
5

我無法弄清楚這裏發生了什麼。對range函數附加引用可以在索引3處創建遞歸列表。範圍函數對Python列表有什麼作用?

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

然而,當我試試這個:

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

我可以很容易地推斷對於第二種情況的原因,但不能夠了解哪些附加參考range功能是做給追加列表。

+3

這是爲什麼標記Python 2和3? 'range'在2和3中的行爲不同。 – interjay

+2

列表通過python中的引用傳遞。這意味着在第一種情況下,您將指針附加到x,而不是x的值。因爲x現在包含一個指向x的指針,所以它在該點遞歸地調用它自己。 –

+0

@JacobH:說「列表通過引用傳遞」使得它看起來像列表可能與其他對象的行爲不同。所有的對象都以相同的方式傳遞(雖然人們爭論什麼是正確的短語來描述) – DSM

回答

9

在python2中,range s是list s。

list s,而大部分在Python的東西都對象身份

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

既然你把名單內本身,你要創建一個遞歸數據結構。

+4

請注意,這是Python 2特有的,範圍在Python 3中完全不同,返回一個懶惰評估的'範圍'對象,而不是一個列表 – MattDMo

+0

@Karoly謝謝你的答案,但我不明白爲什麼賦值5的工作原理無論我學到了什麼,如果我使用[1 ] [0] = 5,那麼它意味着在索引1列表中分配5到0索引。 – Rahul

+0

如果你的意思是我的例子:'li [1]'是'li',所以它只是'li [0] = 5'。 –

0

首先這很奇怪,你可能不應該在實踐中使用它。該問題不是特定於range函數,而是與引用有關。當您撥打x.append(x)時,您基本上會說x[-1] is x。所以,當你修改x[0],你還可以修改x[-1][0]x[-1][-1][0]

要看到,這是不特定的範圍內,你可以使用copy.copy

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 

輸出:

(0, 0, 0) 
(1, 1, 1) 
(0, 0) 
(1, 0) 
相關問題