QML not taking ownership of object received from PyQt slot

后端 未结 1 379
春和景丽
春和景丽 2021-01-01 03:12

What is the correct way to call a Python function from QML that will instantiate and return an object to QML, and have QML side be responsible for the lifetime of the object

相关标签:
1条回答
  • 2021-01-01 03:35

    In short: using SIP Python API to transfer ownership to C++ while keeping the Python "part" of a QObject alive seemingly solves the issue, which is indeed an ownership one, as covered at (also see the comments in sources below):

    • http://www.commandprompt.com/community/pyqt/x2393.htm
    • http://www.commandprompt.com/community/pyqt/x2420.htm
    • http://pyqt.sourceforge.net/Docs/sip4/using.html#ref-object-ownership

    On SIP API, see:

    • http://pyqt.sourceforge.net/Docs/sip4/python_api.html
    • http://pyqt.sourceforge.net/Docs/sip4/c_api.html#c.sipTransferTo
    • http://www.riverbankcomputing.com/pipermail/pyqt/2005-October/011263.html

    Also, some nice general advice is at:

    • https://stackoverflow.com/a/11945184/110118

    A slightly modified example from the question, Python source:

    from PyQt5.QtGui import QGuiApplication
    from PyQt5.QtQuick import QQuickView
    from PyQt5.QtCore import QUrl, QObject, QVariant, pyqtSlot
    from PyQt5.QtQml import QQmlEngine, qmlRegisterType
    import sip
    
    def ownership(obj):
        jsOwned = QQmlEngine.objectOwnership(obj) == QQmlEngine.JavaScriptOwnership
        return "Javascript" if jsOwned else "Cpp"  
    
    def onDummytDestroyed():
        print "Dummy destroyed"
    
    class Dummy(QObject):
    
        i = 0
    
        def __init__(self):
            #let's not forget to properly initialize the base part
            super(Dummy, self).__init__()
            self.i = Dummy.i
            Dummy.i = Dummy.i + 1
    
        def __del__(self):
            #let's track when the Python part gets destroyed 
            #  (or, rather, "finalized", or whatever the correct term is :) )
            print "Dummy.__del__(), self.i:", self.i
    
        @pyqtSlot(result="QString")
        def get_str(self):
            #let's have a Python (not C++) implemented method in the class
            return "Dummy string #" + str(self.i)
    
    class GUIEntryPoint(QObject):
    
        def __init__(self):
            #same as with Dummy.__init__
            super(GUIEntryPoint, self).__init__()
    
        @pyqtSlot(result=QVariant) #would also work
        #@pyqtSlot(result=QObject)
        def get_foo(self):
            print "GUIEntryPoint.get_foo():"
            foo = Dummy()
            foo.setObjectName("Foo")
    
            #let's track when the C++ part gets destroyed
            foo.destroyed.connect(onDummytDestroyed)
    
            #this would destroy the Python part of foo as soon as the reference
            #goes out of scope (the C++ part stay alive and will be properly accessible from QML,
            #but attempts to access Python-implemented methods like Dummy.get_str()
            #would cause a TypeError hinting that there is no such method) 
            #sip.transferto(foo, None)
    
            #this works as expected, with both Python (and then C++) parts of foo
            #being destroyed whenever the QML GC decides to get rid of the object
            #(see program output, notice how GC is silent for a while)  
            sip.transferto(foo, foo)
    
            #this is indeed not needed, as proper ownership will be set
            #when the object passes to the QML land through the slot invocation
            #QQmlEngine.setObjectOwnership(foo, QQmlEngine.JavaScriptOwnership)
            print "    initial ownership: ", ownership(foo)
    
            return foo
    
        @pyqtSlot(QObject) #would also work
        #@pyqtSlot(QVariant) 
        def print_foo(self, foo):
            print "GUIEntryPoint.print_foo():"
            print "    objectName: ", foo.objectName()
            print "    ownership when on QML side: ", ownership(foo)
    
    app = QGuiApplication([])
    view = QQuickView()
    
    #not needed, indeed, as both context objects (and properties),
    #and QObject descendants passed to QML side are perfectly accessible
    #(that is, their properties and invokables / slots are) 
    #without any additional steps
    #(instantiating types declaratively would require registering them first, though,
    #and having properties of custom types requires metatypes to be declared)
    #qmlRegisterType(GUIEntryPoint, 'GUIEntryPoint', 1, 0, 'GUIEntryPoint')
    #qmlRegisterType(Dummy, 'Dummy', 1, 0, 'Dummy')
    
    gep = GUIEntryPoint()
    view.rootContext().setContextProperty('BE', gep)
    
    view.setSource(QUrl.fromLocalFile("pyqt-ownership-test.qml"))
    view.show()
    
    app.exec_()
    

    QML source (save as pyqt-ownership-test.py):

    import QtQuick 2.1
    
    Rectangle {
        width: 300
        height: 200
        color: "red"
        border.width: 10
    
        Component.onCompleted: {
            console.log("Component.onCompleted():")
    
            //increase the number to 1000 to see GC stepping in
            //while the loop is still running
            //(notice how destruction is not being reported for some objects,
            //for example, #249 (the one created last),
            //but this looks like a Qt/QML logging issue)
            for (var i = 0; i < 250; i++) {
                console.log("#" + i)
                var foo = BE.get_foo()
    
                console.log("    foo: " + foo)
                console.log("    foo.objectName: " + foo.objectName)
                console.log("    foo.get_str(): " + foo.get_str())
    
                console.log("    print_foo():")
                BE.print_foo(foo)
            }
        }
    }
    

    Program output (stripped in the middle to accomodate SO answer size limit):

    Component.onCompleted():
    #0
    GUIEntryPoint.get_foo():
        initial ownership:  Cpp
        foo: Dummy(0x22903d0, "Foo")
        foo.objectName: Foo
        foo.get_str(): Dummy string #0
        print_foo():
    GUIEntryPoint.print_foo():
        objectName:  Foo
        ownership when on QML side:  Javascript
    #1
    GUIEntryPoint.get_foo():
        initial ownership:  Cpp
        foo: Dummy(0x2290d20, "Foo")
        foo.objectName: Foo
        foo.get_str(): Dummy string #1
        print_foo():
    GUIEntryPoint.print_foo():
        objectName:  Foo
        ownership when on QML side:  Javascript
    #2
    GUIEntryPoint.get_foo():
        initial ownership:  Cpp
        foo: Dummy(0x2291080, "Foo")
        foo.objectName: Foo
        foo.get_str(): Dummy string #2
        print_foo():
    GUIEntryPoint.print_foo():
        objectName:  Foo
        ownership when on QML side:  Javascript
    #3
    GUIEntryPoint.get_foo():
        initial ownership:  Cpp
        foo: Dummy(0x22911e0, "Foo")
        foo.objectName: Foo
        foo.get_str(): Dummy string #3
        print_foo():
    GUIEntryPoint.print_foo():
        objectName:  Foo
        ownership when on QML side:  Javascript
    #4
    GUIEntryPoint.get_foo():
        initial ownership:  Cpp
        foo: Dummy(0x2291e90, "Foo")
        foo.objectName: Foo
        foo.get_str(): Dummy string #4
        print_foo():
    GUIEntryPoint.print_foo():
        objectName:  Foo
        ownership when on QML side:  Javascript
    #5
    GUIEntryPoint.get_foo():
        initial ownership:  Cpp
        foo: Dummy(0x2292b70, "Foo")
        foo.objectName: Foo
        foo.get_str(): Dummy string #5
        print_foo():
    GUIEntryPoint.print_foo():
        objectName:  Foo
        ownership when on QML side:  Javascript
    #6
    GUIEntryPoint.get_foo():
        initial ownership:  Cpp
        foo: Dummy(0x2293420, "Foo")
        foo.objectName: Foo
        foo.get_str(): Dummy string #6
        print_foo():
    GUIEntryPoint.print_foo():
        objectName:  Foo
        ownership when on QML side:  Javascript
    #7
    GUIEntryPoint.get_foo():
        initial ownership:  Cpp
        foo: Dummy(0x2296e30, "Foo")
        foo.objectName: Foo
        foo.get_str(): Dummy string #7
        print_foo():
    GUIEntryPoint.print_foo():
        objectName:  Foo
        ownership when on QML side:  Javascript
    #8
    GUIEntryPoint.get_foo():
        initial ownership:  Cpp
        foo: Dummy(0x22983b0, "Foo")
        foo.objectName: Foo
        foo.get_str(): Dummy string #8
        print_foo():
    GUIEntryPoint.print_foo():
        objectName:  Foo
        ownership when on QML side:  Javascript
    #9
    GUIEntryPoint.get_foo():
        initial ownership:  Cpp
        foo: Dummy(0x2299150, "Foo")
        foo.objectName: Foo
        foo.get_str(): Dummy string #9
        print_foo():
    GUIEntryPoint.print_foo():
        objectName:  Foo
        ownership when on QML side:  Javascript
    #10
    GUIEntryPoint.get_foo():
        initial ownership:  Cpp
        foo: Dummy(0x2299e60, "Foo")
        foo.objectName: Foo
        foo.get_str(): Dummy string #10
        print_foo():
    GUIEntryPoint.print_foo():
        objectName:  Foo
        ownership when on QML side:  Javascript
    #11
    GUIEntryPoint.get_foo():
        initial ownership:  Cpp
        foo: Dummy(0x229ab70, "Foo")
        foo.objectName: Foo
        foo.get_str(): Dummy string #11
        print_foo():
    GUIEntryPoint.print_foo():
        objectName:  Foo
        ownership when on QML side:  Javascript
    
    <...some lines skipped here...>
    
    #245
    GUIEntryPoint.get_foo():
        initial ownership:  Cpp
        foo: Dummy(0x23007b0, "Foo")
        foo.objectName: Foo
        foo.get_str(): Dummy string #245
        print_foo():
    GUIEntryPoint.print_foo():
        objectName:  Foo
        ownership when on QML side:  Javascript
    #246
    GUIEntryPoint.get_foo():
        initial ownership:  Cpp
        foo: Dummy(0x22fe4d0, "Foo")
        foo.objectName: Foo
        foo.get_str(): Dummy string #246
        print_foo():
    GUIEntryPoint.print_foo():
        objectName:  Foo
        ownership when on QML side:  Javascript
    #247
    GUIEntryPoint.get_foo():
        initial ownership:  Cpp
        foo: Dummy(0x22fc5c0, "Foo")
        foo.objectName: Foo
        foo.get_str(): Dummy string #247
        print_foo():
    GUIEntryPoint.print_foo():
        objectName:  Foo
        ownership when on QML side:  Javascript
    #248
    GUIEntryPoint.get_foo():
        initial ownership:  Cpp
        foo: Dummy(0x22fa730, "Foo")
        foo.objectName: Foo
        foo.get_str(): Dummy string #248
        print_foo():
    GUIEntryPoint.print_foo():
        objectName:  Foo
        ownership when on QML side:  Javascript
    #249
    GUIEntryPoint.get_foo():
        initial ownership:  Cpp
        foo: Dummy(0x22f57b0, "Foo")
        foo.objectName: Foo
        foo.get_str(): Dummy string #249
        print_foo():
    GUIEntryPoint.print_foo():
        objectName:  Foo
        ownership when on QML side:  Javascript
    Dummy.__del__(), self.i: 214
    Dummy destroyed
    Dummy.__del__(), self.i: 213
    Dummy destroyed
    Dummy.__del__(), self.i: 212
    Dummy destroyed
    Dummy.__del__(), self.i: 211
    Dummy destroyed
    Dummy.__del__(), self.i: 210
    Dummy destroyed
    Dummy.__del__(), self.i: 209
    Dummy destroyed
    Dummy.__del__(), self.i: 208
    Dummy destroyed
    Dummy.__del__(), self.i: 207
    Dummy destroyed
    Dummy.__del__(), self.i: 206
    Dummy destroyed
    Dummy.__del__(), self.i: 205
    Dummy destroyed
    Dummy.__del__(), self.i: 204
    Dummy destroyed
    Dummy.__del__(), self.i: 203
    Dummy destroyed
    Dummy.__del__(), self.i: 202
    Dummy destroyed
    Dummy.__del__(), self.i: 201
    Dummy destroyed
    Dummy.__del__(), self.i: 200
    Dummy destroyed
    Dummy.__del__(), self.i: 199
    Dummy destroyed
    Dummy.__del__(), self.i: 198
    Dummy destroyed
    Dummy.__del__(), self.i: 197
    Dummy destroyed
    Dummy.__del__(), self.i: 196
    Dummy destroyed
    Dummy.__del__(), self.i: 195
    Dummy destroyed
    Dummy.__del__(), self.i: 194
    Dummy destroyed
    Dummy.__del__(), self.i: 193
    Dummy destroyed
    Dummy.__del__(), self.i: 192
    Dummy destroyed
    Dummy.__del__(), self.i: 191
    Dummy destroyed
    Dummy.__del__(), self.i: 190
    Dummy destroyed
    Dummy.__del__(), self.i: 189
    Dummy destroyed
    Dummy.__del__(), self.i: 188
    Dummy destroyed
    Dummy.__del__(), self.i: 187
    Dummy destroyed
    Dummy.__del__(), self.i: 186
    Dummy destroyed
    Dummy.__del__(), self.i: 185
    Dummy destroyed
    Dummy.__del__(), self.i: 184
    Dummy destroyed
    Dummy.__del__(), self.i: 183
    Dummy destroyed
    Dummy.__del__(), self.i: 182
    Dummy destroyed
    Dummy.__del__(), self.i: 181
    Dummy destroyed
    Dummy.__del__(), self.i: 180
    Dummy destroyed
    Dummy.__del__(), self.i: 179
    Dummy destroyed
    Dummy.__del__(), self.i: 178
    Dummy destroyed
    Dummy.__del__(), self.i: 177
    Dummy destroyed
    Dummy.__del__(), self.i: 176
    Dummy destroyed
    Dummy.__del__(), self.i: 175
    Dummy destroyed
    Dummy.__del__(), self.i: 174
    Dummy destroyed
    Dummy.__del__(), self.i: 173
    Dummy destroyed
    Dummy.__del__(), self.i: 172
    Dummy destroyed
    Dummy.__del__(), self.i: 171
    Dummy destroyed
    Dummy.__del__(), self.i: 170
    Dummy destroyed
    Dummy.__del__(), self.i: 169
    Dummy destroyed
    Dummy.__del__(), self.i: 168
    Dummy destroyed
    Dummy.__del__(), self.i: 167
    Dummy destroyed
    Dummy.__del__(), self.i: 166
    Dummy destroyed
    Dummy.__del__(), self.i: 165
    Dummy destroyed
    Dummy.__del__(), self.i: 164
    Dummy destroyed
    Dummy.__del__(), self.i: 163
    Dummy destroyed
    Dummy.__del__(), self.i: 162
    Dummy destroyed
    Dummy.__del__(), self.i: 161
    Dummy destroyed
    Dummy.__del__(), self.i: 160
    Dummy destroyed
    Dummy.__del__(), self.i: 159
    Dummy destroyed
    Dummy.__del__(), self.i: 158
    Dummy destroyed
    Dummy.__del__(), self.i: 157
    Dummy destroyed
    Dummy.__del__(), self.i: 156
    Dummy destroyed
    Dummy.__del__(), self.i: 155
    Dummy destroyed
    Dummy.__del__(), self.i: 154
    Dummy destroyed
    Dummy.__del__(), self.i: 153
    Dummy destroyed
    Dummy.__del__(), self.i: 152
    Dummy destroyed
    Dummy.__del__(), self.i: 151
    Dummy destroyed
    Dummy.__del__(), self.i: 150
    Dummy destroyed
    Dummy.__del__(), self.i: 149
    Dummy destroyed
    Dummy.__del__(), self.i: 148
    Dummy destroyed
    Dummy.__del__(), self.i: 147
    Dummy destroyed
    Dummy.__del__(), self.i: 146
    Dummy destroyed
    Dummy.__del__(), self.i: 145
    Dummy destroyed
    Dummy.__del__(), self.i: 144
    Dummy destroyed
    Dummy.__del__(), self.i: 143
    Dummy destroyed
    Dummy.__del__(), self.i: 142
    Dummy destroyed
    Dummy.__del__(), self.i: 141
    Dummy destroyed
    Dummy.__del__(), self.i: 140
    Dummy destroyed
    Dummy.__del__(), self.i: 139
    Dummy destroyed
    Dummy.__del__(), self.i: 138
    Dummy destroyed
    Dummy.__del__(), self.i: 137
    Dummy destroyed
    Dummy.__del__(), self.i: 136
    Dummy destroyed
    Dummy.__del__(), self.i: 135
    Dummy destroyed
    Dummy.__del__(), self.i: 134
    Dummy destroyed
    Dummy.__del__(), self.i: 133
    Dummy destroyed
    Dummy.__del__(), self.i: 132
    Dummy destroyed
    Dummy.__del__(), self.i: 131
    Dummy destroyed
    Dummy.__del__(), self.i: 130
    Dummy destroyed
    Dummy.__del__(), self.i: 129
    Dummy destroyed
    Dummy.__del__(), self.i: 128
    Dummy destroyed
    Dummy.__del__(), self.i: 127
    Dummy destroyed
    Dummy.__del__(), self.i: 126
    Dummy destroyed
    Dummy.__del__(), self.i: 125
    Dummy destroyed
    Dummy.__del__(), self.i: 124
    Dummy destroyed
    Dummy.__del__(), self.i: 123
    Dummy destroyed
    Dummy.__del__(), self.i: 122
    Dummy destroyed
    Dummy.__del__(), self.i: 121
    Dummy destroyed
    Dummy.__del__(), self.i: 120
    Dummy destroyed
    Dummy.__del__(), self.i: 119
    Dummy destroyed
    Dummy.__del__(), self.i: 118
    Dummy destroyed
    Dummy.__del__(), self.i: 117
    Dummy destroyed
    Dummy.__del__(), self.i: 116
    Dummy destroyed
    Dummy.__del__(), self.i: 115
    Dummy destroyed
    Dummy.__del__(), self.i: 114
    Dummy destroyed
    Dummy.__del__(), self.i: 113
    Dummy destroyed
    Dummy.__del__(), self.i: 112
    Dummy destroyed
    Dummy.__del__(), self.i: 111
    Dummy destroyed
    Dummy.__del__(), self.i: 110
    Dummy destroyed
    Dummy.__del__(), self.i: 109
    Dummy destroyed
    Dummy.__del__(), self.i: 108
    Dummy destroyed
    Dummy.__del__(), self.i: 107
    Dummy destroyed
    Dummy.__del__(), self.i: 106
    Dummy destroyed
    Dummy.__del__(), self.i: 105
    Dummy destroyed
    Dummy.__del__(), self.i: 104
    Dummy destroyed
    Dummy.__del__(), self.i: 103
    Dummy destroyed
    Dummy.__del__(), self.i: 102
    Dummy destroyed
    Dummy.__del__(), self.i: 101
    Dummy destroyed
    Dummy.__del__(), self.i: 100
    Dummy destroyed
    Dummy.__del__(), self.i: 99
    Dummy destroyed
    Dummy.__del__(), self.i: 98
    Dummy destroyed
    Dummy.__del__(), self.i: 97
    Dummy destroyed
    Dummy.__del__(), self.i: 96
    Dummy destroyed
    Dummy.__del__(), self.i: 95
    Dummy destroyed
    Dummy.__del__(), self.i: 94
    Dummy destroyed
    Dummy.__del__(), self.i: 93
    Dummy destroyed
    Dummy.__del__(), self.i: 92
    Dummy destroyed
    Dummy.__del__(), self.i: 91
    Dummy destroyed
    Dummy.__del__(), self.i: 90
    Dummy destroyed
    Dummy.__del__(), self.i: 89
    Dummy destroyed
    Dummy.__del__(), self.i: 88
    Dummy destroyed
    Dummy.__del__(), self.i: 87
    Dummy destroyed
    Dummy.__del__(), self.i: 86
    Dummy destroyed
    Dummy.__del__(), self.i: 85
    Dummy destroyed
    Dummy.__del__(), self.i: 84
    Dummy destroyed
    Dummy.__del__(), self.i: 83
    Dummy destroyed
    Dummy.__del__(), self.i: 82
    Dummy destroyed
    Dummy.__del__(), self.i: 81
    Dummy destroyed
    Dummy.__del__(), self.i: 80
    Dummy destroyed
    Dummy.__del__(), self.i: 79
    Dummy destroyed
    Dummy.__del__(), self.i: 78
    Dummy destroyed
    Dummy.__del__(), self.i: 77
    Dummy destroyed
    Dummy.__del__(), self.i: 76
    Dummy destroyed
    Dummy.__del__(), self.i: 75
    Dummy destroyed
    Dummy.__del__(), self.i: 74
    Dummy destroyed
    Dummy.__del__(), self.i: 73
    Dummy destroyed
    Dummy.__del__(), self.i: 72
    Dummy destroyed
    Dummy.__del__(), self.i: 71
    Dummy destroyed
    Dummy.__del__(), self.i: 70
    Dummy destroyed
    Dummy.__del__(), self.i: 69
    Dummy destroyed
    Dummy.__del__(), self.i: 68
    Dummy destroyed
    Dummy.__del__(), self.i: 67
    Dummy destroyed
    Dummy.__del__(), self.i: 66
    Dummy destroyed
    Dummy.__del__(), self.i: 65
    Dummy destroyed
    Dummy.__del__(), self.i: 64
    Dummy destroyed
    Dummy.__del__(), self.i: 63
    Dummy destroyed
    Dummy.__del__(), self.i: 62
    Dummy destroyed
    Dummy.__del__(), self.i: 61
    Dummy destroyed
    Dummy.__del__(), self.i: 60
    Dummy destroyed
    Dummy.__del__(), self.i: 59
    Dummy destroyed
    Dummy.__del__(), self.i: 58
    Dummy destroyed
    Dummy.__del__(), self.i: 57
    Dummy destroyed
    Dummy.__del__(), self.i: 56
    Dummy destroyed
    Dummy.__del__(), self.i: 55
    Dummy destroyed
    Dummy.__del__(), self.i: 54
    Dummy destroyed
    Dummy.__del__(), self.i: 53
    Dummy destroyed
    Dummy.__del__(), self.i: 52
    Dummy destroyed
    Dummy.__del__(), self.i: 51
    Dummy destroyed
    Dummy.__del__(), self.i: 50
    Dummy destroyed
    Dummy.__del__(), self.i: 49
    Dummy destroyed
    Dummy.__del__(), self.i: 48
    Dummy destroyed
    Dummy.__del__(), self.i: 47
    Dummy destroyed
    Dummy.__del__(), self.i: 46
    Dummy destroyed
    Dummy.__del__(), self.i: 45
    Dummy destroyed
    Dummy.__del__(), self.i: 44
    Dummy destroyed
    Dummy.__del__(), self.i: 43
    Dummy destroyed
    Dummy.__del__(), self.i: 42
    Dummy destroyed
    Dummy.__del__(), self.i: 41
    Dummy destroyed
    Dummy.__del__(), self.i: 40
    Dummy destroyed
    Dummy.__del__(), self.i: 39
    Dummy destroyed
    Dummy.__del__(), self.i: 38
    Dummy destroyed
    Dummy.__del__(), self.i: 37
    Dummy destroyed
    Dummy.__del__(), self.i: 36
    Dummy destroyed
    Dummy.__del__(), self.i: 35
    Dummy destroyed
    Dummy.__del__(), self.i: 34
    Dummy destroyed
    Dummy.__del__(), self.i: 33
    Dummy destroyed
    Dummy.__del__(), self.i: 32
    Dummy destroyed
    Dummy.__del__(), self.i: 31
    Dummy destroyed
    Dummy.__del__(), self.i: 30
    Dummy destroyed
    Dummy.__del__(), self.i: 29
    Dummy destroyed
    Dummy.__del__(), self.i: 28
    Dummy destroyed
    Dummy.__del__(), self.i: 27
    Dummy destroyed
    Dummy.__del__(), self.i: 26
    Dummy destroyed
    Dummy.__del__(), self.i: 25
    Dummy destroyed
    Dummy.__del__(), self.i: 24
    Dummy destroyed
    Dummy.__del__(), self.i: 23
    Dummy destroyed
    Dummy.__del__(), self.i: 22
    Dummy destroyed
    Dummy.__del__(), self.i: 21
    Dummy destroyed
    Dummy.__del__(), self.i: 20
    Dummy destroyed
    Dummy.__del__(), self.i: 19
    Dummy destroyed
    Dummy.__del__(), self.i: 18
    Dummy destroyed
    Dummy.__del__(), self.i: 17
    Dummy destroyed
    Dummy.__del__(), self.i: 16
    Dummy destroyed
    Dummy.__del__(), self.i: 15
    Dummy destroyed
    Dummy.__del__(), self.i: 14
    Dummy destroyed
    Dummy.__del__(), self.i: 13
    Dummy destroyed
    Dummy.__del__(), self.i: 12
    Dummy destroyed
    Dummy.__del__(), self.i: 11
    Dummy destroyed
    Dummy.__del__(), self.i: 10
    Dummy destroyed
    Dummy.__del__(), self.i: 9
    Dummy destroyed
    Dummy.__del__(), self.i: 8
    Dummy destroyed
    Dummy.__del__(), self.i: 7
    Dummy destroyed
    Dummy.__del__(), self.i: 6
    Dummy destroyed
    Dummy.__del__(), self.i: 5
    Dummy destroyed
    Dummy.__del__(), self.i: 4
    Dummy destroyed
    Dummy.__del__(), self.i: 3
    Dummy destroyed
    Dummy.__del__(), self.i: 2
    Dummy destroyed
    Dummy.__del__(), self.i: 1
    Dummy destroyed
    Dummy.__del__(), self.i: 0
    Dummy destroyed
    
    0 讨论(0)
提交回复
热议问题