首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >PyQT5程序中的垃圾收集机制与正常情况有什么不同?(如果这是与GC相关的问题)

PyQT5程序中的垃圾收集机制与正常情况有什么不同?(如果这是与GC相关的问题)
EN

Stack Overflow用户
提问于 2021-07-18 16:23:20
回答 1查看 140关注 0票数 0

为了了解对象删除特性 of metaclass QObject in PyQT5,我编写了以下代码:

代码语言:javascript
复制
from PyQt5.Qt import *


class Window(QWidget):
    def __init__(self):
        super().__init__()
        self.setup_UI()
        self.setup_subUI()
        self.hook = None

    def setup_UI(self):
        self.setWindowTitle('MyWindowTitle')
        self.resize(600, 400)

    def setup_subUI(self):
        obj1 = QObject()
        obj2 = QObject(obj1)
        obj3 = QObject(obj2)
        self.hook = obj1  # This is line 19.
        obj1.setObjectName('obj1')
        obj2.setObjectName('obj2')
        obj3.setObjectName('obj3')
        obj1.destroyed.connect(lambda obj: print(f'Object {obj.objectName()} has been released'))
        obj2.destroyed.connect(lambda obj: print(f'Object {obj.objectName()} has been released'))
        obj3.destroyed.connect(lambda obj: print(f'Object {obj.objectName()} has been released'))


if __name__ == '__main__':
    import sys

    app = QApplication(sys.argv)
    window = Window()
    window.show()
    sys.exit(app.exec_())

在上面的代码中有几个明显的事实:

obj1;

  • obj1类具有一个非本质属性hook,它最初用于绑定到Windowobj2的父对象,obj2obj3的父对象。如果参考计数不涉及任何对象,则将迅速恢复所有三个对象,以激活下面的destroyed信号接收器,并进一步打印此消息。

为了避免GC,我添加了第19行,试图保留它们,self.hook = obj1,但是它适得其反。

下面是一个谜题:

如果将第19行更改为self.other_attribute_not_schedule = obj1,程序将不会在窗口UI实体关闭之前释放这3个对象。更清楚的是,,你能告诉我更多关于用上面的代码删除对象的详细信息吗,以及为什么当我使用另一行时它们不被删除?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-07-18 17:03:20

当对象的引用数达到0时,垃圾回收就会激活。在这种情况下,python尝试删除它,如果Qt允许的话。

在您的原始代码中,首先调用setup_subUI,它创建一个引用:

代码语言:javascript
复制
self.hook = obj1

然后,在setup_subUI返回之后,执行以下操作:

代码语言:javascript
复制
self.hook = None

这将导致将self.hook“覆盖”为对None的引用,因此删除了前面的引用(obj1)。因为这是唯一的参考,它和它的孩子一起被删除了。

然后,再次在setup_subUI中执行以下操作

代码语言:javascript
复制
self.other_attribute_not_schedule = obj1

setup_subUI返回时,下一行将按上面的方式进行计算:

代码语言:javascript
复制
self.hook = None

这里的区别是,您没有覆盖self.hook,因为它还不存在,而且obj1也没有被删除,因为它的引用(self.other_attribute_not_schedule)仍然存在。

注有不同类型的引用(例如,将对象添加到持久列表中),它们可能并不总是显式的,特别是对于像Qt这样的复杂模块。

例如,将父对象添加到第一个对象的构造函数将防止删除,即使您执行了self.hook = None

代码语言:javascript
复制
obj1 = QObject(self)

这是因为对象的所有权然后由Qt本身管理。

在很多情况下,Qt获得对象的所有权(必要时通过对其进行修复),例如在向布局中添加小部件时,然后将布局设置为另一个小部件。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/68431013

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档