python - 基于引用计数以“错误”顺序调用 Python 析构函数
问题描述
据我了解,当对象的引用计数达到 0 时,应该调用 Python 析构函数。但这种假设似乎不正确。看下面的代码:
class A:
def __init__(self, b):
self.__b = b
print("Construct A")
def __del__(self):
# It seems that the destructor of B is called here.
print("Delete A")
# But it should be called here
class B:
def __init__(self):
print("Construct B")
def __del__(self):
print("Delete B")
b = B()
a = A(b)
输出
Construct B
Construct A
Delete B
Delete A
但是 A 引用了 B,所以我希望得到以下输出:
Construct B
Construct A
Delete A
Delete B
我没有得到什么?
解决方案
因此,由于在解释器关闭时对象仍然存在,因此您实际上甚至不能保证__del__
会被调用。此时,该语言不保证何时调用终结器。
不能保证
__del__()
为解释器退出时仍然存在的对象调用方法。
请注意,如果您将脚本更改为:
(py38) 173-11-109-137-SFBA:~ juan$ cat test.py
class A:
def __init__(self, b):
self.__b = b
print("Construct A")
def __del__(self):
# It seems that the destructor of B is called here.
print("Delete A")
# But it should be called here
class B:
def __init__(self):
print("Construct B")
def __del__(self):
print("Delete B")
b = B()
a = A(b)
del a
del b
然后,执行:
(py38) 173-11-109-137-SFBA:~ juan$ python test.py
Construct B
Construct A
Delete A
Delete B
虽然del
不会删除对象,但它会删除引用,因此它会在解释器仍在运行时强制引用计数达到 0,因此顺序如您所愿。
有时,__del__
根本不会被调用。一个常见的情况是文件对象由
f = open('test.txt')
在全局范围内具有实时引用。如果没有明确关闭,它可能不会调用__del__
并且文件不会刷新并且您不会得到任何写入。这是使用文件对象作为上下文管理器的一个很好的理由......
推荐阅读
- .net - 无法读取配置部分“appSettings”,因为它缺少部分声明
- jasmine - Karma + Jasmine 导致重复警告 WARN: 'Env: not supported, default to development'
- java - 从重定向 URL 的标头中获取位置
- r - 在信息框 Shinydashboard 中打开新窗口
- java - 如何在 JackRabbit 2 中查询存储库描述符表?
- docker - Traefik 代理 ip 身份验证
- python - 从网站中提取属性,然后在 Python 中使用 pandas、bs4 删除列表中的重复元素并将其写入 .xls 文件
- mongodb - pymongo中的Update_one具有不同的字段类型
- mysql - 简单的 MariaDB 自定义函数
- android-studio - Android Studio 构建不关心我的 Gradle 风格?