在MC架构中,相互引用会导致内存泄漏。我如何更改一个好的设计程序?

In the MC architecture, mutual references cause memory leaks. How do I change a good design program?

点击按钮,QTabWidget 将添加一个标签(患者对象)。

我是这样设计的。

首先模型请求网络获取数据后调用patient方法显示数据

其次,患者会主动使用模型中的数据。

所以我定义了self.model=Model()和self.view=view,但是这样就产生了问题。患者和模型相互引用,这将导致内存泄漏。所以当我关闭标签时,我不得不删除 patient.model。属性之间不再相互引用,解决了内存泄露问题

但是,在我的项目中,我有很多视图和模型相互引用的情况。我需要把它们都找出来,然后在关闭标签的时候关闭它们之间的关系。我认为这种设计在内存泄漏方面有点薄弱。你能给我一些更好的设计建议吗?非常感谢。

import sys
from PyQt4 import QtGui
from PyQt4.QtGui import QTabWidget, QHBoxLayout, QWidget, QPushButton


class Model(object):
    def __init__(self, view):
        self.view = view


class Patient(QWidget):
    def __init__(self):
        super(Patient, self).__init__()
        self.model = Model(self)
        self.data = [map(lambda x: {'name': 'ken'}, [x for x in range(10000000)])]


class Tab(QTabWidget):
    def __init__(self):
        super(Tab, self).__init__()
        self.setTabsClosable(True)
        self.tabCloseRequested.connect(self.delete)

    def add(self):
        self.addTab(Patient(), 'name')

    def delete(self, index):
        patient = self.widget(index)
        self.removeTab(index)

        import sip
        sip.delete(patient)
        del patient.model


class Example(QtGui.QWidget):

    def __init__(self):
        super(Example, self).__init__()

        self.initUI()

    def initUI(self):
        self.hbox = QHBoxLayout()
        self.setLayout(self.hbox)

        self.tab = Tab()
        self.hbox.addWidget(self.tab)

        btn = QPushButton()
        btn.clicked.connect(self.click)
        self.hbox.addWidget(btn)

        self.setGeometry(100, 100, 500, 500)
        self.setWindowTitle("PyQt")
        self.show()

    def click(self):
        self.tab.add()


def main():
    app = QtGui.QApplication(sys.argv)
    ex = Example()
    sys.exit(app.exec_())


if __name__ == '__main__':
    main()

如果您总是使用 Model 和 Patient 类,则可以使用 destroyed() 信号在小部件被删除时收到通知,并删除模型。

由于 deleteLater() 还负责断开与销毁对象相关的所有插槽,因此不能在其自己的实例上调用该方法。为了避免这种情况,使用 lambda 可以解决这个问题。

class Patient(QWidget):
    def __init__(self):
        super(Patient, self).__init__()
        self.model = Model(self)
        self.data = [map(lambda x: {'name': 'ken'}, [x for x in range(10000000)])]
        self.destroyed.connect(lambda: self.aboutToBeDeleted())

    def aboutToBeDeleted(self):
        del self.model


class Tab(QTabWidget):
    #...
    def delete(self, index):
        patient = self.widget(index)
        self.removeTab(index)
        patient.deleteLater()

这应该会处理所有事情,包括断开与 patient 相关的所有插槽和信号。调用 deleteLater() 也应该足够了,而不是使用 sip.delete (我相信无论如何都是由 deleteLater 完成的)。