來自:Python之禪(微訊號:VTtalk)
變數與賦值
在 Python 中,一切皆為物件,物件透過「變數名」取用,「變數名」更確切的叫法是「名字」,好比我們每個人都有自己的名字一樣,咱們透過名字來代指某個人,程式碼裡面透過名字來指代某個物件。
變數賦值就是給物件系結一個名字,賦值並不會複製物件。好比我們出生的時候父母就要給我們取一個名字一樣,給人取個綽號並不來多出一個人來,只是多一個名字罷了。
兩個物件做比較有兩種方式,分別是:is 與 == ,is
比較的是兩個物件是否相同,透過物件的ID值可識別是否為相同物件,==
比較的是兩個物件的值是否相等
>>> x1 = [1,2]
>>> x2 = [1,2]
>>> x1 is x2
False
>>> id(x1)
4338854088
>>> id(x2)
4338904392
>>> x1 == x2
True
x1 和 x2 的值雖然相同,但在記憶體中是兩個獨立的不同的物件,佔據不同的記憶體空間,就好比兩個長得一樣的蘋果擺在桌子上,實則為兩個不同的物體。
>>> x3 = x2
>>> x3 is x2
True
>>> id(x3)
4338904392
前面說了,賦值是給物件系結名字,這裡我們只不過是給 x2 對應的那個物件系結了一個新的名字叫 x3,這就好比桌上放了一個蘋果,開始給它貼了一個 x2 的標簽,後來又給它添了一個 x3 的標簽,本質上還是同一個蘋果,所以,x2 和 x3 所指的其實是同一個物件。
透過x2 修改物件時,x3 也會跟著變化,因為本質上它們是同一個物件,這就好比張三和小張是同一個人時,給張三添衣服其實就是給小張添衣服。
>>> x2.append(3)
>>> x2
[1, 2, 3]
>>> x3
[1, 2, 3]
但是,當我給 x2 重新賦值時,相當於 x2 不再取用之前的物件,而取用新物件, x3 依然取用之前的物件。好比桌上一大蘋果開始貼了 x2 和 x3 兩個標簽,給 x2 重新賦值就相當於把 x2 標簽貼到另外一個蘋果,但是 x3 還是貼在老蘋果身上。
>>> x2 = [3, 4]
>>> x3
[1, 2, 3]
物件複製
在業務中有時我們需要複製一個物件,但是又不想對原物件產生副作用,肯定不能透過賦值給一個新變數來解決(因為賦值不是複製物件),所以 Python 專門提供了一種複製機制,基於原物件快速創建出一個含有相同值的物件。該功能由copy
模組提供。
複製又分為淺複製和深複製。
>>> s = [1,2,3]>>> sc = copy.copy(s) # 淺複製>>> sc[1, 2, 3]
>>> sdc = copy.deepcopy(s) # 深複製
>>> sdc
[1, 2, 3]
複製出來的物件只是值相同,實為不同的物件
>>> s == sc == sdc
True
>>> s is sc
False
>>> s is sdc
False
那麼淺複製(shallow copy)與深複製(deep copy)有什麼區別呢?
對於不可變物件,比如整數、字串、元組、還有由這些不可變物件組成的集合物件,淺複製和深複製沒有區別,都是複製一個新物件
兩者的區別在於複製組合物件,比如串列中還有串列,字典中還有字典或者串列的情況時,淺複製只複製了外面的殼子,裡面的元素並沒有複製,而深複製則是把殼子和裡面的元素都複製了一份新的。
來看一個例子:
>>> x = [2, 3]
>>> y = [7, 11]
>>> z = [x, y]
>>> a = copy.copy(z) # 淺複製
>>> a[0] is z[0]
True
複製出來的物件 a 中的元素取用的是 x 和 y,當你修改 x 的值,a 也會跟著變。
>>> b = copy.deepcopy(z) # 深複製
>>> b[0] is z[0]
False
對於深複製,裡面的元素也重新複製了一份,複製了一份與x和y等值的兩個元素,修改 x 和 y 的值,不會對 b 產生影響
對串列的切片複製z[:]
或者是呼叫物件的copy方法list.copy()
都屬於淺複製。對於自定義物件,我們還可以自己實現__copy__
方法和__deepcopy__
方法
●編號391,輸入編號直達本文
●輸入m獲取文章目錄
演演算法與資料結構
更多推薦:《18個技術類微信公眾號》
涵蓋:程式人生、演演算法與資料結構、駭客技術與網路安全、大資料技術、前端開發、Java、Python、Web開發、安卓開發、iOS開發、C/C++、.NET、Linux、資料庫、運維等。