初步探索
编程中最常见的赋值语句也很有内涵,变量名就像一个handle,间接控制对象。id函数可以获取对象的真实地址,相同地址即同一对象,(ob1 is ob2) 等价于 (id(ob1) == id(ob2))。我们可以利用id和is探索赋值语句。
1 | # True |
但在产生代理对象时有一个例外情况
1 | def bar(this, x): |
因为foo.bar是表达式的计算结果
回收算法
CPython Garbage Collector 有三种回收思路:
1. reference count 引用计数
1 | import sys |
当使用变量名传递给getrefcount()时,实际同时创建了一个函数作用域内的临时引用。因为结果会多1。当引用计数为0则释放对象。可以通过globals()查看全局引用字典。
2. mark and sweep and reference cycle 标记清除
两个对象互相引用,或一个对象自己引用自己,会产生循环引用。
1 | a = [] |
循环引用给内存释放造成了麻烦,CPython 用 标记清除算法 解决循环引用问题: 先将引用环的计数复制一个副本,遍历对象集合,操作副本,依次减一。计数值为0的对象设为unreachable,可以被回收。
3. generation collection 分代回收
内存块根据其存活时间划分为不同的集合,每个集合就是一代。Python默认定义了三代对象集合,代数越大,越惰于回收。
我们可以手动调用回收方法
1 | # (700, 10, 10) |
返回值代表,700是启动阈值,生成一个对象时会检查第0代有没有满;每回收十次0代对象集合,启动一次1代回收;每回收十次1代对象集合,启动一次2代回收。
诊断方法
objgraph
referrence
赏
使用支付宝打赏
使用微信打赏
若你觉得我的文章对你有帮助,欢迎点击上方按钮对我打赏
扫描二维码,分享此文章