python3 super 不适用于 PyQt 类

Posted

技术标签:

【中文标题】python3 super 不适用于 PyQt 类【英文标题】:python3 super doesn't work with PyQt classes 【发布时间】:2012-09-10 12:43:42 【问题描述】:

python3中有一个简单的程序:

from PyQt4 import QtCore
import PyQt4

class Bar(object):
    def __init__(self):
        print("Bar start")
        super(Bar, self).__init__()
        print("Bar end")

class FakeQObject(object):
    def __init__(self):
        print("FakeQObject start")
        super(FakeQObject, self).__init__()
        print("FakeQObject end")

class Foo(QtCore.QObject, Bar):
#class Foo(FakeQObject, Bar):
    def __init__(self):
        print("Foo start")
        super(Foo, self).__init__()
        print("Foo end")


print(Foo.__mro__)
print(PyQt4.QtCore.PYQT_VERSION_STR)
f = Foo()

a) 当 Foo 类从 QtCore.QObject 和 Bar 继承时,我们得到:

(<class '__main__.Foo'>, <class 'PyQt4.QtCore.QObject'>, <class 'sip.wrapper'>, <class 'sip.simplewrapper'>, <class '__main__.Bar'>, <class 'object'>)
4.9.4
Foo start
Foo end

b) 当类 Foo 继承自 FakeQObject 和 Bar 时,我们得到:

(<class '__main__.Foo'>, <class '__main__.FakeQObject'>, <class '__main__.Bar'>, <class 'object'>)
4.9.4
Foo start
FakeQObject start
Bar start
Bar end
FakeQObject end
Foo end

问题是:为什么在 a) 的情况下,Bar init 没有被调用?

我在这里pyQt4 and inheritance 发现了类似的问题,但没有好的答案。

提前致谢!

【问题讨论】:

我怀疑这是因为QtCore.QObject 没有使用合作super.__init__。顺便说一句,在 Python 3 中,您不需要 super(Foo, self)super() 应该足够了。 是的,但是 PyQt 站点 riverbankcomputing.co.uk/static/Docs/PyQt4/html/gotchas.html 说:“在 v4.5 之前的 PyQt 版本中,对使用 super 和 PyQt 类有限制。这些限制不再适用于 v4.5 和之后。”所以,这是 PyQt 的一个 bug,不是吗? 感谢 super() 没有参数,不知道.. 有什么原因不能在继承顺序中将Bar 移动到QObject 之前? 在我的项目中,我已经这样做了。但是,语言/库/任何东西的限制决定了应用程序设计,这是不自然和可悲的。 【参考方案1】:

除了@nneonneo,我还怀疑QtCore.QObject 不使用合作super.__init__。如果是这样,你就不会有这个问题了。

但是,您应该知道,在某些时候,基类之一不能使用协作超级,因为object 没有该方法。考虑:

class Base():
    def __init__(self):
        print("initializing Base")
        super().__init__()
    def helper(self, text):
        print("Base helper")
        text = super().helper(text)
        text = text.title()
        print(text)

class EndOfTheLine():
    def __init__(self):
        print("initializing EOTL")
        super().__init__()
    def helper(self, text):
        print("EOTL helper")
        text = super().helper(text)
        return reversed(text)

class FurtherDown(Base, EndOfTheLine):
    def __init__(self):
        print("initializing FD")
        super().__init__()
    def helper(self, text):
        print(super().helper(text))

test = FurtherDown()
print(test.helper('test 1 2 3... test 1 2 3'))

和输出:

initializing FD
initializing Base
initializing EOTL
Base helper
EOTL helper
Traceback (most recent call last):
  File "test.py", line 28, in <module>
    print(test.helper('test 1 2 3... test 1 2 3'))
  File "test.py", line 25, in helper
    print(super().helper(text))
  File "test.py", line 7, in helper
    text = super().helper(text)
  File "test.py", line 17, in helper
    text = super().helper(text)
AttributeError: 'super' object has no attribute 'helper'

因此,无论哪个类将成为行尾,都不需要调用super。因为您可能想要覆盖其他 Qt 方法,这表明 Qt 类必须是类头中的最后一个。通过不让__init__ 使用协作超级,即使它可以,Qt 也可以避免在其他方法被覆盖时进一步降低错误。

【讨论】:

以上是关于python3 super 不适用于 PyQt 类的主要内容,如果未能解决你的问题,请参考以下文章

OpenALPR 不适用于 PyQt

pyinstaller 不适用于 pyqt5 和 matplotlib

多个摄像头馈送不适用于 PyQt5 线程:

PyQt5 keyPressEvent 不适用于终止 App Qt Designer

Python3---常见函数---super()

Pyqt5 鼠标事件不适用于我的自定义标签栏