流畅的python-学习笔记_对象引用、可变性、垃圾回收

发布于:2024-05-07 ⋅ 阅读:(19) ⋅ 点赞:(0)

变量不是盒子

即变量是引用,而不是实际内存,多个标识赋值相同变量时,多余标识是引用

标识、相等性、别名

==比较对象的值,is比较对象的id。==实际调用对象的__eq__方法。is速度比==快,因为is不能重载,省去了寻找方法的时间

元组不可变性

默认浅复制

即=或copy复制的是容器最浅层的容器元素,嵌套元素复制的是元素引用而非元素本身

深复制用copy.deepcopy即可。深复制可处理循环引用,不会陷入无限循环,但深复制后,调用仍存在循环引用

函数传参

py默认共享传参,也是引用传参,即函数的参数为入参的引用。当入参可变对象时,函数内可能会修改入参对象。若不希望参数被改变,可考虑参数可变性

但不要给默认参数设置可变对象,比如空列表。这会导致实例对该默认参数绑定到类的属性上:ClassName.__init__.___defaults__

del和垃圾回收

Cpython是python的一个解释器,cpython中,垃圾回收机制主要为引用计数,当对象的引用为0时,解释器调用对象的__del__方法。cpython2.0增加了分代垃圾回收算法,可解决循环引用问题

del后如何检测对象是否被删除?可用weakref模块:

发现引用为0立即dead了。del不会明确删除对象,而是删除引用,靠解释器回收机制删除对象

注意 weakref对x也有引用,但对象最后还是被删除了,为啥?因为weakref是弱引用

弱引用

弱引用不会增加对象的引用数量,即不会妨碍回收机制回收对象

不推荐直接用weakref.ref监控对象,可以用WeakKeyDictionary,WeakValueDictionary,finalize或WeakSet

WeakValueDictionary

weakvaluedictionary常用于缓存,他是一种可变map,值是对象弱引用,被引用对象被垃圾回收后,值对应的键会自动删除。weakkeydictionary的键是对象弱引用,和weakvaluedictionary做区分

weakkeydictionary由于key是弱引用,可用来给对象添加附加属性

弱引用局限性

弱引用不可以引用list或dict类型,但可以引用他们的派生类。但int和tuple也不能引用,即使派生类也不能引用,原因是cpython的一些实现细节导致

python对于不可变类型

用对象入参重新创对象,若是不可变类型(比如tuple),会创建对象引用,而非全新对象:

这种现象可称为驻留,是cpython的一种优化措施。

所以比较时,尽量用==而不要用is,否则可能会因为驻留现象受到影响