在 python 中賦值語句總是建立對象的引用值,而不是復制對象。因此,python 變量更像是指針,而不是數據存儲區域,
這點和大多數 OO 語言類似吧,比如 C++、java 等 ~
1、先來看個問題吧:
在Python中,令values=[0,1,2];values[1]=values,為何結果是[0,[...],2]?
>>> values = [0, 1, 2]>>> values[1] = values>>> values[0, [...], 2]
我預想應當是
[0, [0, 1, 2], 2]
但結果卻為何要賦值無限次?
可以說 Python 沒有賦值,只有引用。你這樣相當于創建了一個引用自身的結構,所以導致了無限循環。為了理解這個問題,有個基本概念需要搞清楚。
Python 沒有「變量」,我們平時所說的變量其實只是「標簽」,是引用。
執行
values = [0, 1, 2]
的時候,Python 做的事情是首先創建一個列表對象 [0, 1, 2],然后給它貼上名為 values 的標簽。如果隨后又執行
values = [3, 4, 5]
的話,Python 做的事情是創建另一個列表對象 [3, 4, 5],然后把剛才那張名為 values 的標簽從前面的 [0, 1, 2] 對象上撕下來,重新貼到 [3, 4, 5] 這個對象上。
至始至終,并沒有一個叫做 values 的列表對象容器存在,Python 也沒有把任何對象的值復制進 values 去。過程如圖所示:
執行
values[1] = values
的時候,Python 做的事情則是把 values 這個標簽所引用的列表對象的第二個元素指向 values 所引用的列表對象本身。執行完畢后,values 標簽還是指向原來那個對象,只不過那個對象的結構發生了變化,從之前的列表 [0, 1, 2] 變成了 [0, ?, 2],而這個 ? 則是指向那個對象本身的一個引用。如圖所示:
要達到你所需要的效果,即得到 [0, [0, 1, 2], 2] 這個對象,你不能直接將 values[1] 指向 values 引用的對象本身,而是需要吧 [0, 1, 2] 這個對象「復制」一遍,得到一個新對象,再將 values[1] 指向這個復制后的對象。Python 里面復制對象的操作因對象類型而異,復制列表 values 的操作是
values[:] #生成對象的拷貝或者是復制序列,不再是引用和共享變量,但此法只能頂層復制
所以你需要執行
values[1] = values[:]
Python 做的事情是,先 dereference 得到 values 所指向的對象 [0, 1, 2],然后執行 [0, 1, 2][:] 復制操作得到一個新的對象,內容也是 [0, 1, 2],然后將 values 所指向的列表對象的第二個元素指向這個復制二來的列表對象,最終 values 指向的對象是 [0, [0, 1, 2], 2]。過程如圖所示:
新聞熱點
疑難解答