轉載:https://www.cnblogs.com/huamingao/p/5809936.html
核心提示:
可變類型 Vs 不可變類型
可變類型(mutable):列表,字典
不可變類型(unmutable):數字,字符串,元組
這里的可變不可變,是指內存中的那塊內容(value)是否可以被改變
代碼:
name1='wupeiqi' name2=name1 print("name1:%s\nname2:%s" %(name1,name2)) name1='alex' print("I have renamed name1 to new_name.Let's see what happens!")
print("name1:%s\nname2:%s" %(name1,name2))
執行結果:
C:/Personal/OldboyPython/day01/test.py name1:wupeiqi name2:wupeiqi I have renamed name1 to new_name.Let's see what happens! name1:alex name2:wupeiqi
疑問:為什么name2的值沒有和name1一起變為alex?下面開始解答,先看圖,后解釋。
以下引用自http://www.cnblogs.com/wupeiqi/articles/5433925.html
變量的賦值
#!/usr/bin/env python # -*- coding: utf-8 -*- name1 = "wupeiqi" name2 = "alex"
#!/usr/bin/env python # -*- coding: utf-8 -*- name1 = "wupeiqi" name2 = name1 # 使name2和name1指向同一個對象 賦值,只是創建一個變量,該變量指向原來內存地址,
1.引用計數的增減
當對象wupeiqi(圖中藍色的內存區塊wupeiqi)被初次創建並(將其引用)賦值給變量name1時,對象wupeiqi的引用計數被設置為1。
當對象alex(圖中藍色的內存區塊alex)被初次創建並(將其引用)賦值給變量name2時,對象alex的引用計數被設置為1。
當變量name1賦值給變量name2(name2=name1),實際是把對象wupeiqi賦值給name2,因此對象wupeiqi的引用計數自動加1,而對象alex的引用計數自動減1,即減為0,觸發垃圾回收機制。
2. 可變類型 Vs 不可變類型
可變類型(mutable):列表,字典
不可變類型(unmutable):數字,字符串,元組
這里的可變不可變,是指內存中的那塊內容(value)是否可以被改變。如果是不可變類型,在對對象本身操作的時候,必須在內存中新申請一塊區域(因為老區域#不可變#)。如果是可變類型,對對象操作的時候,不需要再在其他地方申請內存,只需要在此對象后面連續申請(+/-)即可,也就是它的address會保持不變,但區域會變長或者變短。
可以使用內建函數id()來確認對象的身份在兩次賦值前后是否發生了變化。示例可參看http://blog.chinaunix.net/uid-26249349-id-3080279.html
*不可變類型有什么好處?如果數據是不可變類型,當我們把數據傳給一個不了解的API時,可以確保我們的數據不會被修改。如果我們要操作一個從函數返回的元組,可以通過內建函數list()把它轉換成一個列表。(當被問到列表和元組的區別時,可以說這一點!)
3. 深拷貝 Vs 淺拷貝
copy.copy() 淺拷貝
copy.deepcopy() 深拷貝
淺拷貝是新創建了一個跟原對象一樣的類型,但是其內容是對原對象元素的引用。這個拷貝的對象本身是新的,但內容不是。拷貝序列類型對象(列表\元組)時,默認是淺拷貝。
以下引用自http://www.cnblogs.com/wupeiqi/articles/5433925.html
賦值,只是創建一個變量,該變量指向原來內存地址,如下例:
n4 = n3 = n2 = n1 = "123/'Wu'"
關於賦值,再看一個字典的例子:
n1 = {"k1": "wu", "k2": 123, "k3": ["alex", 678]} n2 = n1
淺拷貝,在內存中只額外創建第一層數據,如下圖
深拷貝,在內存中將所有的數據重新創建一份(排除最后一層,即:python內部對字符串和數字的優化),如下圖:
import copy n1 = {"k1": "wu", "k2": 123, "k3": ["alex", 456]} n4 = copy.deepcopy(n1)