第八章 - 对象引用、可变性和垃圾回收
对象引用、可变性和垃圾回收
本章先以一个比喻说明 Python的变量: 变量是标签,而不是盒子。
8.1 变量不是盒子
可变对象赋值 就是引用同一个对象, 不可变对象赋值则是复制一个副本。
Python说明标识不通的方式: a is not b
在Cpython中, id() 返回对象的内存地址。
8.2 在 == 和 is 之间选择
"=="运算符比较两个对象的“值”,而is比较对象的引用。
is运算符比 == 速度快, 是因为它不能重载(详见重载运算符),所以Python不用寻找并调用特殊方法,而是直接比较两个整数ID,而 a == b 是语法糖, 等同于a.__eq__(b)。
在变量和单例值之间比较时,应该使用is, 最常使用is检查变量绑定的值是不是None。
x is None. x is not None
a = [1,2,3] b = [1,2,3] c = a print(a is b) >>> False print(c is a) >>> True
比较字符串或整数是否相等时,应该使用 == , 而不是is。
8.3 默认做浅复制
也就是说容器内的可变对象还只是一个引用。
浅复制共享内部对象引用, 深复制不共享内部对象引用。
class Bus(object): def __init__(self, passengers=None): if passengers is None: self.passengers = [] # 注意这里接收的是一个可变对象 else: self.passengers = list(passengers) # 注意这里不是简单的引用,而是使用list创建了一个副本 def pick(self, name): self.passengers.append(name) def drop(self, name): self.passengers.remove(name)
注意: 不要使用可变类型作为参数的默认值, 因此通常使用None作为接收可变对象的参数的默认值。
8.5 del和垃圾回收
del语句删除名次,而不是对象。 del不删除对象,而是删除对象引用。
在Cpython中,垃圾回收使用的主要算法是引用计数;实际上每个对象都会统计有多少引用指向自己,当引用计数归零时,对象立即就被销毁。
弱引用不会增加对象的引用数量, 弱应用不会妨碍所指对象被当作垃圾回收。
弱引用在缓存应用中很有用,因为我们不想仅因为被缓存引用着而始终保存缓存对象。
内置函数weaker.ref提供弱引用