Python重复赋值同名类实例变量异常输出及计数错误原因求解
执行逻辑解释
核心原因是Python的引用计数垃圾回收规则和类的__del__析构方法的触发机制,逐步骤拆解如下:
第一步:首次执行 p1 = Person('p1')
- 新建
Person实例,触发__init__方法打印Initializing p1,类属性population从0变为1 - 变量
p1指向这个新实例,实例引用计数为1,不会触发析构,无额外输出,符合预期。
第二步:第二次执行 p1 = Person('p1')
赋值操作的执行顺序是先计算等号右侧的值,再做变量绑定,所以执行流程为:
- 先执行
Person('p1')创建第二个Person实例,触发__init__打印Initializing p1,population加1变为2 - 将新实例绑定到变量名
p1,此时原来p1指向的第一个实例失去这个引用,引用计数降为0,触发第一个实例的__del__方法 - 第一个实例的
__del__执行时打印p1 says bye,population减1变为1,因此打印there are still 1 people left
这就是你看到两行输出的原因。
第三步:执行 p1 = Person('p2')仅输出初始化内容、howMany()返回2的原因
此时赋值时旧实例(第二步创建的第二个Person实例)没有触发__del__,说明该实例的引用计数没有降到0,常见于交互式运行环境(比如Jupyter Notebook、IPython):这类环境会缓存历史输入输出对象,持有实例的额外引用,导致旧实例不会被回收。
此时存活的实例有2个:第二步创建的未被回收的实例、刚创建的p2实例,因此howMany()返回2。
补充说明
- 不要在业务逻辑中依赖
__del__的执行时机,不同Python运行环境的垃圾回收行为可能存在差异,__del__仅在实例引用计数归0时才会被触发。 population是类级别的共享属性,所有实例共享同一个值,变化对所有实例可见。
内容的提问来源于stack exchange,提问作者Mahali Sindy
相关产品推荐
相关产品推荐

