python中的循环引用

2024-01-14

我不确定python如何处理循环引用(引用循环)。我检查了一些答案并发现this https://stackoverflow.com/questions/8025888/does-python-gc-deal-with-reference-cycles-like-this:

Python 的标准引用计数机制无法释放循环,因此示例中的结构会泄漏。
然而,补充垃圾收集设施默认情况下处于启用状态,并且应该能够释放该结构,如果它的任何组件都不再可以从外部访问并且它们没有__del__()方法。

我想这意味着如果引用循环中的任何实例都无法从外部访问,那么它们都将被清理。这是真的?
另一方面,有一个包weakref常用于处理地图字典。我认为它存在的目的是为了避免引用循环。
综上所述,python可以自动处理引用循环吗?如果可以,为什么我们必须使用weakref?


如果循环中的对象没有自定义,则不必担心引用循环__del__方法,因为 Python 可以(并且将会)以任何顺序销毁对象。

如果您的自定义方法确实有__del__方法中,Python 根本不知道一个对象的删除是否会影响另一个对象的删除。假设当一个对象被删除时,它会设置一些全局变量。因此,物体会留在周围。作为快速测试,您可以进行__del__打印一些东西的方法:

class Deletor(str):
    def __del__(self):
        print(self, 'has been deleted')

a = Deletor('a')  # refcount: 1
del a             # refcount: 0

Outputs:

a has been deleted

但如果你有这样的代码:

a = Deletor('a')  # refcount: 1
a.circular = a    # refcount: 2
del a             # refcount: 1

它不输出任何内容,因为 Python 无法安全删除a。它变成了“无法收集的物品”,并且可以在以下位置找到:gc.garbage https://docs.python.org/3/library/gc.html#gc.garbage

对此有两种解决方案。这weakref(这不会增加引用计数):

# refcount:             a  b
a = Deletor('a')      # 1  0
b = Deletor('b')      # 1  1
b.a = a               # 2  1
a.b = weakref.ref(b)  # 2  1
del a                 # 1  1
del b                 # 1  0
# del b kills b.a     # 0  0

Outputs:

b has been deleted
a has been deleted

(注意如何b先删除后才能删除a)

您可以手动删除周期(如果您可以跟踪它们):

# refcount          a  b
a = Deletor('a')  # 1  0
b = Deletor('b')  # 1  1
b.a = a           # 2  1
a.b = b           # 2  2
del b             # 2  1
print('del b')
del a.b           # 2  0
# b is deleted, now dead
# b.a now dead    # 1  0
print('del a.b')
del a             # 0  0
print('del a')

Outputs:

del b
b has been deleted
del a.b
a has been deleted
del a

注意如何b被删除after a.b被删除。


† 从 Python 3.4 开始,事情发生了变化,因为PEP 442 https://www.python.org/dev/peps/pep-0442/. __del__即使在引用循环中的对象上也可能被调用,并且语义略有不同,因此成为不可收集对象稍微困难一些。

A weakref仍然有帮助,因为它对垃圾收集器的强度较小,并且可以更早地回收内存。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

python中的循环引用 的相关文章

随机推荐

  • python-tz 是我错了还是它是一个错误

    这似乎有点奇怪 当我想用 pytz 获取欧洲 巴黎时区时 它让我进入 PMT 时区 而不是 GMT 1 当它似乎适用于欧洲 柏林时 不清楚 看看这个片段 usr bin python import os import datetime fr
  • `numpy.argmax()` 的理论平均情况运行时复杂度

    我正在看代码numpy argmax功能 我很困惑哪种数据结构numpy维持为argmax功能 https numpy org doc stable reference generated numpy argmax html https n
  • 使用 VS 项目检查代码的 xslt 将 Xml 转换为 html

    我有一个InspectionResults xml当我运行时生成的inspectcode exe from JetbrainsCommandLine Tool Analysis 有没有xslt提供的文件Jetbrains将此 xml 转换为
  • 使用 setuptools 创建 python 可执行文件

    我有一个小的 python 应用程序 我想将其制作为类 UNIX 系统的可下载 可安装的可执行文件 我的印象是安装工具将是实现这一目标的最佳方法 但不知何故 这似乎不是一项常见任务 我的目录结构如下所示 myappname setup py
  • Kafka 连接到节点 ubuntukafka 时出错:9092(id:0 机架:null)(org.apache.kafka.clients.NetworkClient)java.net.UnknownHostException:

    我在 VirtualBox 来宾上有两台服务器 每个服务器都是 ubuntu 我可以从我的主机通过 SSH 连接到两台机器 以及两台机器之间的 SSH 这样它们都具有 natnetwork 我在一台服务器 kafka 上运行 如下所述 ht
  • Python 格式最佳实践

    我刚刚熟悉 Python 并且有一个关于在字符串上使用 format 的最佳实践 或至少是常见实践 的问题 我的问题主要是关于何时使用空白大括号 索引号和名称 例如 如果您想将一个变量包含在字符串中 您会选择哪一个 print I Stac
  • NASM:磁盘读取超时

    尝试从磁盘 从同一文件 读取数据 将另外 2 个 512 字节扇区加载到内存中 磁盘读取功能如下 read DH sectors to ES BX from drive DL disk read push dx push bx Tried
  • Google Apps 脚本 location.reload 在网络应用程序中

    我正在使用一个 GAS Web 应用程序 当用户执行某些操作 例如单击特定的 div 时 该应用程序需要刷新其内容 在客户端 我有一个从 onclick 调用的脚本 google script run withSuccessHandler
  • 在 swift 3 iOS 中实现谷歌翻译 api

    你好 我是 iOS 开发新手 我正在尝试在我的应用程序中实现谷歌翻译 API 我从GitHub上在线找到了一些示例代码https github com prine ROGoogleTranslate https github com pri
  • 无法更改 rgl 图中的文本大小

    我在更改使用 rgl 包生成的 3d 绘图的文本大小时遇到 问题 一切工作正常 但我无法有效地更改 3d 对象的 cex 属性 我在 64 位 Ubuntu 10 04 LTS 2 6 32 37 generic 下运行 R 2 14 1
  • 构造函数中的同步以使其发生在之前

    我有一个关于如何通过 Java 内存模型保证对象是线程安全的问题 我读过很多文章 说在构造函数中编写同步作用域没有意义 但为什么没有意义呢 是的 确实 只要正在构造的对象不在线程之间共享 这不应该是 除了构造线程之外 没有任何线程可以到达任
  • 与 ARM LDR 指令关联的哈希 (#) 值是什么意思?

    我正在尝试调试我的应用程序中遇到的崩溃 堆栈跟踪指向具有以下格式的 LDR 指令 感谢反汇编程序 LDR R3 R0 4 我的问题是关于源组件的 第二个参数中的 4是什么意思 我假设它是某种偏移量 但我还没有找到支持 LDR 指令的文档 它
  • DataTable 和线程安全

    我将 DataTable 存储在 ASP NET Cache 属性中 可以对该 DataTable 执行的操作有 绑定到网格控件 第 3 方网格内部管理数据源对象 回发后其 DataSource 为 NULL 我假设一旦绑定数据 它就不再使
  • MavenProject:获取在我的插件上使用的可用类

    我正在按照描述加载 Maven 项目here https stackoverflow com questions 4381460 get mavenproject from just the pom xml pom parser 我正在尝试
  • 定期分割字符串

    我想定期分割字符串 我的问题与这个问题几乎相同 如何将一个字符串分割成给定长度的子串 https stackoverflow com questions 11619616 how to split a string into substri
  • SubSonic 和存储过程

    使用 SubSonic 时 您是否将数据作为数据集返回 或者将其放入强类型自定义集合或通用对象中 我运行了 subsonic 项目 对于数据库中的四个存储过程 它为我提供了一个 Sps cs 其中包含 4 个返回 StoredProcedu
  • 如何访问数组的对象(stdClass 对象)成员/元素的属性? [复制]

    这个问题在这里已经有答案了 Doing print r 在我的阵列上我得到以下信息 Array 0 gt stdClass Object id gt 25 time gt 2014 01 16 16 35 17 fname gt 4 tex
  • 双除法的错误行为

    我有一个HashMap called List
  • 如何在 Antd 表中使用 Radio 组?

    我想这样做 每一行都是一个Radio组 每个单元格都是一个Radio按钮 如图 Radio 组的示例如下
  • python中的循环引用

    我不确定python如何处理循环引用 引用循环 我检查了一些答案并发现this https stackoverflow com questions 8025888 does python gc deal with reference cyc