You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python调用sys.getrefcount()时析构函数意外触发的原因咨询

问题分析与解答

首先明确两次触发__del__的具体原因:

第一次触发__del__(执行b = f()时)

执行b = a()后,变量b指向a类的实例,此时实例的引用计数为1。当执行b = f(),b被重新赋值为字符串'something',原来的a实例失去所有引用,引用计数降为0,Python垃圾回收机制自动调用该实例的__del__方法,输出getting rid of something,这是正常的对象销毁逻辑。

第二次触发__del__(调用sys.getrefcount(b)时)

你提到调用sys.getrefcount(b)时触发__del__并返回3,核心原因是交互环境的额外引用与函数调用的临时引用共同作用:

  1. 交互环境的内置变量引用:Python交互shell会将最后一次执行的表达式结果赋值给内置变量_。如果调用sys.getrefcount(b)前,你曾直接输入b查看实例,_会额外引用该实例,此时实例引用计数变为2(b + _)。
  2. sys.getrefcount的临时引用:调用该函数时,参数传递会临时增加实例的引用计数1,此时总引用计数为3(b + _ + 函数参数),因此getrefcount返回3。
  3. 引用计数回落触发销毁:函数执行完毕后,临时的参数引用被释放;当你输入新命令时,内置变量_会被新结果覆盖,原来的实例引用计数降为0,从而触发__del__方法。

另外,你的__del__方法中del self是多余的——__del__本身就是对象销毁前的回调,此时self是对象的最后一个局部引用,del self不会改变对象的销毁逻辑,反而容易造成误解。

验证示例

在交互shell中执行以下步骤可复现该现象:

>>> import sys
>>> class a:
...     def __del__(self):
...             print('getting rid of something')
...
>>> b = a()
>>> b  # 此时_会引用该实例,引用计数变为2
<__main__.a object at 0x10xxxxxx>
>>> sys.getrefcount(b)  # 总引用计数为3,返回3
3
>>> 1+1  # 输入新命令,_被新结果覆盖
2
getting rid of something  # 实例引用计数降为0,触发__del__

内容的提问来源于stack exchange,提问作者KARAN CHOUDHARY

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 17:45:00