標籤:
1. Python引用計數[ http://blog.chinaunix.net/uid-26602509-id-3506965.html ]
1.1 引用計數機制
引用計數是電腦程式設計語言中的一種記憶體管理技術,是指將資源(可以是對象、記憶體或磁碟空間等等)的被引用次數儲存起來,當被引用次數變為零時就將其釋放的過程。使用引用計數技術可以實現自動資源管理的目的。同時引用計數還可以指使用引用計數技術回收未使用資源的記憶體回收演算法。
當建立一個對象的執行個體並在堆上申請記憶體時,對象的引用計數就為1,在其他對象中需要持有這個對象時,就需要把該對象的引用計數加1,需要釋放一個對象時,就將該對象的引用計數減1,直至對象的引用計數為0,對象的記憶體會被立刻釋放。
1.2 記憶體回收
當對象的引用計數為0,對象的記憶體會被立刻釋放,稱為記憶體回收。
1.3 引用計數增加情況
(1). 對象被建立:x=4
(2). 另外的別人被建立:y=x
(3). 被作為參數傳遞給函數:foo(x)
(4). 作為容器物件的一個元素:a=[1,x,‘33‘]
1.4 引用計數減少情況
(1). 一個本地引用離開了它的範圍。比如上面的foo(x)函數結束時,x指向的對象引用減1。
(2). 對象的別名被顯式的銷毀:del x ;或者del y
(3). 對象的一個別名被賦值給其他對象:x=789
(4). 對象從一個視窗對象中移除:myList.remove(x)
(5). 視窗對象本身被銷毀:del myList,或者視窗對象本身離開了範圍。
2. 深淺拷貝[ http://www.cnblogs.com/wait123/archive/2011/10/10/2206580.html ]
2.1 賦值
其實python中的賦值其實是使引用計數+1,例如:
foo1 = 1.0foo2 = foo1
foo1 is foo2 #True
id(foo1) = 18719720
id(foo2) = 18719720
但是如果是這樣:
foo1=1.0foo2=1.0foo1 is foo2 #False
id(foo1) = 18719888
id(foo2) = 18719840
這時你會發現,這其實是建立了兩個不同的對象,用內建函數id()可以發現,二者的身份不同。
其實python還有一個特例,例如:
a = 1b = 1id(a) = 14332248id(b) = 14332248
原因是python認為這些小整型是會經常用到的,所以python會緩衝一部分小整型。
2.2 深拷貝 & 淺拷貝
序列類型的可以通過三種方式實現淺拷貝,淺拷貝也是預設的拷貝類型:(1)完全切片操作;(2)利用工廠函數,比如list()等;(3)使用copy模組中的copy()函數。
在《Python核心編程》一書中說道,“對一個對象進行淺拷貝其實是新建立了一個類型跟原對象一樣,其內容是原來對象元素的引用,換句話說,這個拷貝的對象本身是新的,但是它的內容不是”。
import copya = [1, 2, 3, 4, [‘a‘, ‘b‘, ‘c‘]]b = ac = copy.copy(a)id(a) #139879301469392id(b) #139879301469392 id(c) #139879298646816, 可以看出所謂的“拷貝對象本身是新的“[id(x) for x in a] #[14332248, 14332224, 14332200, 14332176, 139879298781912][id(x) for x in b] #[14332248, 14332224, 14332200, 14332176, 139879298781912][id(x) for x in c] #[14332248, 14332224, 14332200, 14332176, 139879298781912], 即”內容是舊的“
最後,深拷貝和淺拷貝的區別^_^
import copya = [1, 2, 3, 4, [‘a‘, ‘b‘, ‘c‘]]c = copy.copy(a)d = copy.deepcopy(a)id(a) #139879301469392 id(c) #139879298646816id(d) #139879301462784[id(x) for x in a] #[14332248, 14332224, 14332200, 14332176, 139879298781912][id(x) for x in c] #[14332248, 14332224, 14332200, 14332176, 139879298781912][id(x) for x in d] #[14332248, 14332224, 14332200, 14332176, 139879302072512]##################################a.append(5)a[4].append(‘hello‘)a #[1, 2, 3, 4, [‘a‘, ‘b‘, ‘c‘, ‘hello‘], 5]c #[1, 2, 3, 4, [‘a‘, ‘b‘, ‘c‘, ‘hello‘]]d #[1, 2, 3, 4, [‘a‘, ‘b‘, ‘c‘]][id(x) for x in a] #[14332248, 14332224, 14332200, 14332176, 139879298781912, 14332152][id(x) for x in c] #[14332248, 14332224, 14332200, 14332176, 139879298781912][id(x) for x in d] #[14332248, 14332224, 14332200, 14332176, 139879302072512]#################################a[1] = 0c[2] = 0d[3] = 0a #[1, 0, 3, 4, [‘a‘, ‘b‘, ‘c‘, ‘hello‘], 5]c #[1, 2, 0, 4, [‘a‘, ‘b‘, ‘c‘, ‘hello‘]]d #[1, 2, 3, 0, [‘a‘, ‘b‘, ‘c‘]][id(x) for x in a] #[14332248, 14332272, 14332200, 14332176, 139879298781912, 14332152] a[1]關聯到新對象
[id(x) for x in c] #[14332248, 14332224, 14332272, 14332176, 139879298781912] c[2]關聯到新對象
[id(x) for x in d] #[14332248, 14332224, 14332200, 14332272, 139879302072512] d[3]關聯到新對象
################################
# 1
del a[0]
a #[ 0, 3, 4, [‘a‘, ‘b‘, ‘c‘, ‘hello‘], 5]
c #[1, 2, 0, 4, [‘a‘, ‘b‘, ‘c‘, ‘hello‘]]
d #[1, 2, 3, 0, [‘a‘, ‘b‘, ‘c‘]]
del c[0]
a #[ 0, 3, 4, [‘a‘, ‘b‘, ‘c‘, ‘hello‘], 5]
c #[ 2, 0, 4, [‘a‘, ‘b‘, ‘c‘, ‘hello‘]]
d #[1, 2, 3, 0, [‘a‘, ‘b‘, ‘c‘]]
del d[0]
a #[ 0, 3, 4, [‘a‘, ‘b‘, ‘c‘, ‘hello‘], 5]
c #[ 2, 0, 4, [‘a‘, ‘b‘, ‘c‘, ‘hello‘]]
d #[ 2, 3, 0, [‘a‘, ‘b‘, ‘c‘]]
# 2
del a[3][0]
a #[ 0, 3, 4, [ ‘b‘, ‘c‘, ‘hello‘], 5]
c #[ 2, 0, 4, [ ‘b‘, ‘c‘, ‘hello‘]]
d #[ 2, 3, 0, [‘a‘, ‘b‘, ‘c‘]]
簡單點說[個人臆想,期待指正]
1. copy.copy 淺拷貝 -元素有的引用計數+1(如a的元素1,2,3,4),獨立的;而有的則沒有(如上面a的元素[‘a‘,‘b‘,‘c‘]),不是完全獨立
2. copy.deepcopy 深拷貝 -元素或者引用計數+1,或者建立新對象,實現完全獨立
#列印[‘a‘,‘b‘,‘c‘]地址
[id(x) for x in a[3]] #[1398793470232, 139879343471752, 139879314380720][id(x) for x in c[3]] #[1398793470232, 139879343471752, 139879314380720][id(x) for x in d[3]] #[1398793470192, 139879343470232, 139879343471752]
Python深拷貝和淺拷貝