对象引用、可变性和垃圾回收
变量不是盒子,它是对象的标识
- 标识、相等性和别名
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']
[]