深入理解python之一——python3物件的一些特性

B1u3Buf4發表於2018-09-05

文章使用markdown寫的,編輯的時候行間距還可以,顯示的時候行間距好小,我也沒辦法。

首先,需要明白的是python是一種解釋性語言標準,他可以由c、java或者其他語言來實現。在python的標準中,變數是連結式的。舉個例子來說,記憶體中的物件和變數就像是給記憶體物件貼變數名標籤而不是給變數盒子裝入東西(數值資訊)。或者說是給物件分配變數名,而不是給變數賦值。因為python物件在執行賦值之前就已經創立存在了的。

物件標識和變數名

id()返回物件的標識,cpython中id()返回的是唯一的記憶體地址,變數名則是一個便於理解的別名。

is和==的區別

is需要值和記憶體地址都相等,==只需要值相等。對於此更直觀的表示可以執行一下id(),就可以看到不同。
is比==更快,不能過載,直接比較的是id。

變數的可變性

在基礎階段,很多教程都會提到,元祖是不可變的資料型別,所以沒有插入和刪除的操作,只能一次定義。但深究這個問題起來,其實元祖只是在引用上不能變化,但引用的物件是可變的,就導致元祖的值會跟著列表發生變化。淺複製時,多個變數引用同一列表地址,那麼改變一個其他也會變。深複製是在記憶體中重新開闢一個區域,將原來的物件包括其中為物件引用的內容,一同複製到新的區域,並建立新的引用。引用變數的可變性看的是最小物件單位的型別,比如不可變元組中有可變列表物件,列表就是最小的單位,要看它的可變性。列表是可變的,這種特性使得在指向同一個列表物件的情況下,列表實際的長度和值是可以改變的。對其他的型別物件一般不可變,也就不會發生上述變化。

最大的威脅在於,將列表作為引數傳給類方法的時候,類變數和引數繫結了同一個物件,執行完返回後原來的傳入引數的物件發生了變化。除了刻意要去改傳入的列表,否則應該在這之前深複製一個副本,不影響原來的變數的使用。

建立列表的幾種寫法

a = [1,2,3]
b=a
b is a
>>True

c = list(a)
c is a
>>False

d = a[:]
d is a
>>False

類似上面使用b=a這樣的辦法建立的列表,其實只是新建了一個引用,並沒有新建一個物件。如果改變a、b其中一個,另一個會隨著改變。

深複製和淺複製的具體區別

copy模組可以完成淺複製和深複製,分別對應方法copy()和deepcopy()。其中,deepcopy()可以完成對包含迴圈引用的物件的拷貝。

具體可以用下面的a分別做兩種拷貝,會發現其中深拷貝得到的a[1]的內容和另外兩者是不一一樣的。

a = (1,[2,3],(4,5))

使用兩種拷貝分別複製後檢視結果。

相關文章