PyQt QObject Unexpected Shared State
昨天晚上我一直在和一只特别令人困惑的虫子争论。
我写了一些概念验证代码来展示这个问题。
POC码1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | # Standard Imports import sys # Import Core Qt modules from PyQt4.QtGui import QApplication from PyQt4.QtCore import QObject class Bar(QObject): def __init__(self, parent): QObject.__init__(self, parent) self.parent = parent class Foo(QObject): items = [] def __init__(self, parent, item_count=2): QObject.__init__(self, parent) self.parent = parent # Create some items for _ in range(item_count): self.items.append(Bar(self)) # Debug print"QObject Foo Items: %s" % self.items print"QObject Foo Children: %s" % self.children() # Start up main PyQT Application loop app = QApplication(sys.argv) # Build Foo classes aFoo = Foo(app) aFoo2 = Foo(app) # Exit program when our window is closed. sys.exit(app.exec_()) |
执行此代码时,这里是
1 2 3 4 | QObject Foo Items: [<__main__.Bar object at 0x0234F078>, <__main__.Bar object at 0x0234F0C0>] QObject Foo Children: [<__main__.Bar object at 0x0234F078>, <__main__.Bar object at 0x0234F0C0>] QObject Foo Items: [<__main__.Bar object at 0x0234F078>, <__main__.Bar object at 0x0234F0C0>, <__main__.Bar object at 0x0234F150>, <__main__.Bar object at 0x0234F198>] QObject Foo Children: [<__main__.Bar object at 0x0234F150>, <__main__.Bar object at 0x0234F198>] |
代码解释
代码正在创建两个
当第二个类打印出它的
如果您将类变量定义
当
在写这个问题的时候,我找到了答案。
解释当
不过,在完成之前,有一些gotcha类型的情况是由于
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | class Bar(object): aList = ["Hello World"] aString ="Hello World" def __init__(self, new=None): if new is not None: self.aList = new self.aString = new[0] a = Bar() print a.aList, a.aString b = Bar(["Goodbye World"]) print a.aList, a.aString print b.aList, b.aString |
这里的类静态变量是一个名为
1 2 3 4 | # Output ['Hello World'] Hello World ['Hello World'] Hello World ['Goodbye World'] Goodbye World] |
这是很容易理解的输出。类上的静态变量没有改变,如
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | class Bar(object): aList = [] aString ="A" def __init__(self, append=False): if append: self.aList.append('A') self.aString += 'A' a = Bar() print a.aList, a.aString b = Bar(append=True) print a.aList, a.aString print b.aList, b.aString |
和以前一样,但我们只是将
1 2 3 4 | # Output [] A ['A'] A ['A'] AA |
哦!怎么搞的?
我们的字符串类静态变量
我们的列表类静态变量出乎意料。与我们在字符串变量中看到的行为不同,静态列表变量在第二个
我们在示例中看到的
阅读这个问题和这个问题,了解更多关于Python中静态类变量的信息。
关于python中可变/不可变对象的更多信息可以在这里和这里阅读(外部链接)。