2015-11-12 52 views
3

爲什麼說:Python中的變量複製是如何工作的?

>>> a = 1 
>>> b = a 
>>> a = 2 
>>> print(a) 
2 
>>> print(b) 
1 

...但:

>>> a = [3, 2, 1] 
>>> b = a 
>>> a.sort() 
>>> print(b) 
[1, 2, 3] 

我的意思是,爲什麼變量真正複製和迭代器只是引用?

+1

在我看來,這是學習Python中最難的部分之一:學習要告訴你,當*之間的差異以現有對象並修改它*和當你*取一個現有的名字並且指向一個不同的對象時* – turbulencetoo

+0

@turbulencetoo:很簡單。這裏沒有任何例子*複製*對象。對象可能有多個名稱。名稱可能在不同的時間涉及不同的對象。 [這張圖片可能提供了一個見解](http://python.net/~goodger/projects/pycon/2007/idiomatic/handout.html#python-has-names) – jfs

回答

6

變量不是「真正複製」的。變量是對象的名稱,賦值運算符將名稱綁定到運算符右側的對象。更詳細地說:

>>> a = 1表示「使a的名稱引用對象1」。

>>> b = a的意思是「使b名稱指目前由a所指的對象。這是1

>>> a = 2的意思是‘使a名字指的是對象2。’這有哪個對象沒有影響其他任何事指1現指,如b

在你的第二個例子,既ab是指同一個列表對象名稱。a.sort()突變了該對象,並且由於這兩個變量引用了相同的對象,所以在兩個名稱下都可以看到突變的效果。

+0

另請參閱關於這些答案的更詳細和更詳細的討論:http://stackoverflow.com/questions/986006/how-do-i-pass-a-variable-by-reference和http:// stackoverflow。com/questions/534375/passing-values-in-python –

+0

我認爲它也值得我們對可變性做一個簡短的解釋,並說爲什麼,比如說a + = 1在b和a都不會改變'b'如果a和b都是列表,則'a + = [1]'將注意到 –

2

將分配的變量看作指向保存值的內存位置的指針。您實際上可以使用id獲取內存位置。

a = 1 
b = a 

>>> id(a) 
4298171608 

>>> id(b) 
4298171608 # points to the same memory location 

a = 2 
>>> id(a) 
4298171584 # memory location has changed 

做與您的清單例子一樣,你可以看到,這兩個其實都是同一個對象上進行操作,但不同的變量都指向同一個內存位置。

a = [3, 2, 1] 
b = a 
a.sort() 

>>> id(a) 
4774033312 

>>> id(b) 
4774033312 # Same object 
+1

請注意,返回內存位置的'id'是一個實現細節 - 對於常見的C python實現是true,但並不保證在所有實現中都是true。可靠的是,如果兩個對象的id相同,則對象是相同的。什麼'id'意味着像整數和字符串這樣的不可變對象是一個更復雜的問題 - 通常你不應該關心什麼,因爲它們是不可變的。 –

0

在您的第一個示例中,您已將b值設爲a後重新分配了a的值。所以a和b帶有不同的值。

如果您已將一個新的排序列表重新分配,而不是將其排序,則在第二個示例中也會發生同樣的情況。

a = [3,2,1] 
b = a 
a.sort() 
print b 
[1,2,3] 

但是......

a = [3,2,1] 
b = a 
sorted(a) 
print b 
[3,2,1] 
相關問題