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

Python中仅删除一个对象却触发两个对象析构的原因

Python中仅删除一个对象却触发两个对象析构的原因

嗨,这个问题其实和Python的对象生命周期管理,以及程序退出时的自动清理机制有关,我来给你拆解清楚:

首先梳理下你程序的实际执行流程

你写的代码执行步骤是这样的:

  1. 创建对象a,ball_count变为1,打印创建信息;
  2. 创建对象b,ball_count变为2,打印创建信息;
  3. 执行del a:此时a的引用计数降为0,触发它的__del__方法,ball_count变回1,你看到了a的析构日志;
  4. 打印剩余球的数量;
  5. 程序执行到末尾,开始自动退出。

关键原因:Python程序退出时会自动清理所有剩余对象

你看到的b的析构日志,并不是因为你del a导致的,而是当Python脚本执行完毕时,它会自动回收当前进程中所有还存在的对象——也就是你的b对象。这时候b的__del__方法会被调用,所以你会误以为是del a触发了它的析构。

同样的,当你换成del b时:

  • del b触发b的析构,ball_count变为1;
  • 程序继续执行到末尾,a对象还存在,所以程序退出时会自动清理a,触发a的__del__方法;
  • 最终你还是会看到两个对象的析构日志。

验证这个结论的小实验

你可以给程序加一段暂停代码,就能清晰看到区别:

import time

class TennisBall:
    ball_count = 0    
    
    def __init__(self, serial_number, age):
        self.serial_number = serial_number
        self.age = age
        print("New Tennis Ball created {}!".format(self.serial_number))
        TennisBall.ball_count +=1
        
    def __del__(self):
        print("Tennis ball {} has been deleted :(".format(self.serial_number))
        TennisBall.ball_count -= 1


a = TennisBall(1234, 0)
print("Num balls: {} ".format(TennisBall.ball_count))

b = TennisBall(2345, 0)
print("Num balls: {} ".format(TennisBall.ball_count))

del a
print("Num balls after del ball a: {} ".format(TennisBall.ball_count))

# 新增暂停代码,观察析构时机
time.sleep(5)
print("程序即将退出")

运行这段代码你会发现:

  • 执行del a后,只有a的析构日志打印出来;
  • 接下来的5秒sleep期间,完全没有b的析构日志;
  • 只有当sleep结束,print("程序即将退出")执行完,程序彻底退出时,b的析构日志才会出现。

这样就能明确:第二个对象的析构是程序退出的自动清理行为,和你主动del第一个对象没有直接关系。

备注:内容来源于stack exchange,提问作者user4805834

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.14 16:03:03