从QML调用Python函数的正确方法是什么,它将实例化并将对象返回给QML,并让QML负责对象的生命周期?我面临的问题是,对象在达到QML之前就会被垃圾收集。
请注意,我不想在Python端保持对对象的显式引用,并且根据the documentation中的以下引用,我所寻找的甚至应该是默认行为:
当数据从C ++传输到QML时,数据的所有权 始终使用C ++。 此规则的例外是QObject 从显式C ++方法调用返回:在这种情况下,QML 引擎承担对象的所有权 ...
我创建了一个演示问题的最小可运行示例(gist link):
main.py:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import os
import sys
import signal
from PyQt5.QtGui import QGuiApplication
from PyQt5.QtQuick import QQuickView
from PyQt5.QtCore import QUrl, QObject, QVariant, pyqtSlot
from PyQt5.QtQml import QQmlEngine, qmlRegisterType
class Dummy(QObject):
def __del__(self):
print("Deleted")
class GUIEntryPoint(QObject):
@pyqtSlot(result=QVariant)
def get_foo(self):
foo = Dummy()
print("Created {}".format(foo))
print("Ownership after instantiation: {}".format(QQmlEngine.objectOwnership(foo)))
#QQmlEngine.setObjectOwnership(foo, 1) # has no effect
return foo
@pyqtSlot(QVariant)
def print_foo(self, foo):
print("{}, ownership: {}".format(foo, QQmlEngine.objectOwnership(foo)))
def run():
signal.signal(signal.SIGINT, signal.SIG_DFL)
app = QGuiApplication(sys.argv)
# these don't seem to make a difference
qmlRegisterType(GUIEntryPoint, 'GUIEntryPoint', 1, 0, 'GUIEntryPoint')
qmlRegisterType(Dummy, 'Dummy', 1, 0, 'Dummy')
qml_url = QUrl.fromLocalFile(os.path.join('zzz.qml'))
view = QQuickView()
gep = GUIEntryPoint()
view.rootContext().setContextProperty('BE', gep)
view.setSource(qml_url)
view.show()
sys.exit(app.exec_())
if __name__ == '__main__':
run()
zzz.qml:
import QtQuick 2.2
Rectangle {
id: rootItem
width: 640
height: 400
property var pleaseKeepMe: BE.get_foo()
Component.onCompleted: {
console.log("Completed");
BE.print_foo(pleaseKeepMe); // prints None, it has been deleted
console.log("creating another");
var x = BE.get_foo();
// at this point x has already been deleted on the Python side
console.log("created another");
BE.print_foo(x); // prints None
console.log("\n\nPress CTRL-C to exit");
}
}
答案 0 :(得分:3)
简而言之:使用SIP Python API将所有权转移到C ++,同时保持Python“活跃于QObject的一部分”似乎解决了问题,这实际上是一个所有权问题,如下所述(另见下文中的评论) :
在SIP API上,请参阅:
另外,一些不错的一般建议是:
问题的一个略微修改的例子,Python源:
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来源(另存为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)
}
}
}
程序输出(在中间剥离以适应SO答案大小限制):
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