物件引用、可變性和垃圾回收
變數不是盒子,它是物件的標識
- 標識、相等性和別名
charles = {'name':'Chales L.Dogson','born':1832} lewis = charles alex = {'name':'Chales L.Dogson','born':1832} # lewis是charles的別名,is比較的是兩個物件的id print('charles is lewis:',charles is lewis) # alex標識的物件和charles不同 print('charles is alex:',charles is alex) # 但它們的值相等,'=='是語法糖,事實上呼叫的是__eq__ # dict對'=='進行了過載,比較的是物件的內容 print('charles == alex:',charles == alex) 輸出: charles is lewis: True charles is alex: False charles == alex: True
複製
- 複製列表或多數內建可變集合,最簡單的方式是使用內建的型別構造方法
- 預設是淺複製
l1 = [3,[55,44],(7,8,9)] l2 = list(l1) # 複製之後,l2和l1內容相同 print('l2==l1:',l2 == l1) # 但指向不同物件 print('l2 is l1:',l2 is l1) # 但它們內部的元素仍然是同一個物件 print('l2[1] is l1[1]:',l2[1] is l1[1]) # 根據內部元素不同,將會產生不同表現 # 可變元素會相互影響 l1[1].append(33) print('after l1[1] append:') print('l1:',l1) print('l2:',l2) # 不可變元素不會互相影響 l1[2] += (10,) print('after l1[2] append:') print('l1:',l1) print('l2:',l2) 輸出: l2==l1: True l2 is l1: False l2[1] is l1[1]: True after l1[1] append: l1: [3, [55, 44, 33], (7, 8, 9)] l2: [3, [55, 44, 33], (7, 8, 9)] after l1[2] append: l1: [3, [55, 44, 33], (7, 8, 9, 10)] l2: [3, [55, 44, 33], (7, 8, 9)]
- 深複製需要用到copy.deepcopy
from copy import deepcopy l1 = [3,[55,44],(7,8,9)] l2 = deepcopy(l1) # 內部的元素不再是同一個物件 print('l2[1] is l1[1]:',l2[1] is l1[1]) # 無論可變還是不可變元素,都不會相互影響 l1[1].append(33) print('after l1[1] append:') print('l1:',l1) print('l2:',l2) l1[2] += (10,) print('after l1[2] append:') print('l1:',l1) print('l2:',l2) 輸出: l2[1] is l1[1]: False after l1[1] append: l1: [3, [55, 44, 33], (7, 8, 9)] l2: [3, [55, 44], (7, 8, 9)] after l1[2] append: l1: [3, [55, 44, 33], (7, 8, 9, 10)] l2: [3, [55, 44], (7, 8, 9)]
WeakValueDictionary
import weakref class Dog: def __init__(self,name): self.name = name def __repr__(self): return 'Dog(%s)' % self.name # stock儲存一個弱引用的可變對映 stock = weakref.WeakValueDictionary() catalog = [Dog('Alen'),Dog('Bob'),Dog('Wendy')] for dog in catalog: stock[dog.name] = dog print(sorted(stock.keys())) del catalog # 其他Dog物件的引用都消失了,只剩下dog引用了Wendy print(sorted(stock.keys())) # 把dog刪除,Wendy也消失了 del dog print(sorted(stock.keys())) 輸出: ['Alen', 'Bob', 'Wendy'] ['Wendy'] []
WeakKeyDictionary
import weakref class Dog: def __init__(self,name): self.name = name def __repr__(self): return 'Dog(%s)' % self.name # stock儲存一個弱引用的可變對映 stock = weakref.WeakKeyDictionary() catalog = [Dog('Alen'),Dog('Bob'),Dog('Wendy')] # 和WeakValueDictionary不同,WeakKeyDictionary的鍵是被引用的物件 for dog in catalog: stock[dog] = dog.name print([item.name for item in stock.keys()]) del catalog # 其他Dog物件的引用都消失了,只剩下dog引用了Wendy print([item.name for item in stock.keys()]) # 把dog刪除,Wendy也消失了 del dog print([item.name for item in stock.keys()]) 輸出: ['Alen', 'Bob', 'Wendy'] ['Wendy'] []