一,Python的對象:
Python存在大量的對象,我們一般提到的對象都是C中的結構體在堆中申請的一塊內存(以CPython為例),每一個對象都有ID,可以通過ID(Object)獲得。對象的范圍包括內建類型的對象(如int類型的對象123,str的對象"test",list的對象[],生成器對象等等)、用戶自建類型的對象、函數(lambda函數,生成器函數)、類型、Ture、False(bool類型的對象)、None(NoneType的對象)。
1 print id(123) 2 print id("test") 3 print id([]) 4 print id(xrange(1, 3)) 5 print id(lambda v: v) 6 print id(int) 7 print id(True) 8 print id(None) 9 10 print type(123) 11 print type("test") 12 print type([]) 13 print type(xrange(1, 3)) 14 print type(lambda v: v) 15 print type(int) 16 print type(True) 17 print type(None)
1 19257680 2 19062656 3 27888896 4 19590176 5 27863344 6 505361888 7 505379788 8 505354444 9 <type 'int'> 10 <type 'str'> 11 <type 'list'> 12 <type 'xrange'> 13 <type 'function'> 14 <type 'type'> 15 <type 'bool'> 16 <type 'NoneType'>
猜想int類型、True和None都是在高地址中,而動態生成的都是位於低地址中。
二,Python的引用計數:
所有對象都采用引用計數,給對象分配新名詞或者將其放入容器中,這個對象的引用計數都會增加。當離開作用域或者被重新賦值的時候,這個對象的引用計數就會減少。當減少為0,垃圾收集器會將其銷毀。
Python中的對象分為immutable和mutabel,作為immutable的int、char和tuple,相同的值在內存中只會生成一次,每次將其賦值到變量中,便會增加一個引用計數。而作為mutable的list、dict、xrange(生成器)和lambda(函數),每次生成都會在內存中生成一個新的對象。
另外:傳參的時候,若參數為mutable,則傳的是引用,若參數為immutable,則傳的是值。
1 a = 123 #創建一個值為123的對象 2 b = 123 #增加123的引用計數 3 a = 111 #創建一個值為111的對象,減少123的引用計數 4 b = a #增加111的引用計數 5 6 c = [] #創建一個空隊列 7 d = [] #創建一個新的空隊列 8 c = [] #再創建一個新的空隊列,減少原隊列的引用計數 9 c = d #增加d隊列的引用計數,減少c隊列的引用計數 10 c.append(1) #創建一個值為1的對象,不改變原隊列的引用計數
三,Shallow copy和Deep copy的區別
Python document中是這么說的:
- A shallow copy constructs a new compound object and then (to the extent possible) inserts references into it to the objects found in the original.
- A deep copy constructs a new compound object and then, recursively, inserts copies into it of the objects found in the original.
這其中的區別就是淺復制會簡單的復制引用,不管他是mutable還是immutable。而深復制則會遞歸地復制immutable對象引用,對於mutable,則會新建一個對象。
1 import copy 2 a = [1, 2] 3 b = [a, 3] 4 c = copy.copy(b) #c = [[1, 2], 3] 5 d = copy.deepcopy(b) #d = [[1, 2], 3] 6 a.append(3) #c = [[1, 2, 3], 3] 7 #d = [[1, 2], 3]
四,如何控制Shallow copy和Deep copy?
在deepcopy時候,會遇到問題,比如有對象中有一個指向用戶信息的列表,用戶希望在復制的時候直接引用原列表。這個時候可以使用定制功能。
可以在類型中定義__copy__和__deepcopy__實現shallow copy和deep copy,當用戶下次調用copy.copy和copy.deepcopy時,便會調用__copy__和__deepcopy__。
1 import copy 2 class Example(dict): 3 def __init__(self, needcopy={}, userinfo={}): 4 super(Example, self).__init__() 5 self.need = needcopy 6 self.user = userinfo 7 8 def __deepcopy__(self, memo): 9 if memo is None: 10 memo = {} 11 result = self.__class__() 12 memo[id(self)] = result 13 for key in self.need.keys(): 14 result.need = copy.deepcopy(self.need) 15 result.user = self.user 16 return result 17 18 needcopy = {"price": 100} 19 userinfo = {"user": "vincent"} 20 a = Example(needcopy, userinfo) 21 b = copy.deepcopy(a) 22 needcopy["title"] = "no" 23 userinfo["passwd"] = "none" 24 print "need: ", a.need, "; user: ", a.user 25 print "need: ", b.need, "; user: ", b.user

1 need: {'price': 100, 'title': 'no'} ; user: {'passwd': 'none', 'user': 'vincent'} 2 need: {'price': 100} ; user: {'passwd': 'none', 'user': 'vincent'}