pyqt类的方法解析顺序是什么?

时间:2017-10-06 15:09:30

标签: python qt pyqt method-resolution-order

我最近被问及pyqt继承中的一个问题,问题是:假设我有一个方法closeEvent(event)的A类,一个继承A和QMainWindow的类B(因此有一个{{1} } 方法)。 closeEvent(event)的解决方案顺序是什么?考虑到python文档,这将取决于继承顺序。然而,以下示例显示并非如此......是否有人可以提供帮助? 我在使用PyQt5的Windows上使用Python3.6.2。

closeEvent

1 个答案:

答案 0 :(得分:0)

这是一个非常复杂的问题,涉及到协作多继承如何工作时Python和C ++之间的差异。所以我在这里给出的答案更多的是简要概述。我认为对于单个SO答案来说,完整的治疗可能是不可行的。

部分问题在于PyQt如何确定它应该从哪个类继承。这可以通过比较纯Python vs 类层次结构的PyQt版本的__base__属性的值来说明:

class A: pass
class B(QMainWindow): pass
class C(A, B): pass
class D(B, A): pass
class E(QMainWindow, A): pass
class F(A, QMainWindow): pass

print('pyqt:')
print('C:', C.__base__)
print('D:', D.__base__)
print('E:', E.__base__)
print('F:', F.__base__)

class M: pass
class A: pass
class B(M): pass
class C(A, B): pass
class D(B, A): pass
class E(M, A): pass
class F(A, M): pass

print('python:')
print('C:', C.__base__)
print('D:', D.__base__)
print('E:', E.__base__)
print('F:', F.__base__)

输出:

pyqt:
C: <class '__main__.B'>
D: <class '__main__.B'>
E: <class 'PyQt5.QtWidgets.QMainWindow'>
F: <class 'PyQt5.QtWidgets.QMainWindow'>
python:
C: <class '__main__.A'>
D: <class '__main__.B'>
E: <class '__main__.M'>
F: <class '__main__.A'>

这不是错误。这里的差异完全是由于实现细节,我不打算解释(即使我可以)。 PyQt 很可能将其实现更改为与Python行为更紧密地对齐。但它反而选择妥协,而不是偏离Qt / C ++中的工作方式。我猜这个决定受到向后兼容性问题的影响,也许还有维护代码库的难易程度。可能你不得不问问PyQt的作者是否想要在这一点上得到明确的答案。

问题的另一个(更大)部分在于如何在层次结构中的某些类本身不合作时(例如,因为它们是用C ++编写的,就像Qt一样),使合作多继承工作。我认为有可能在某种程度上解决这些问题 - PyQt至少已经为类构造做了这个(见Support for Cooperative Multi-inheritance)。但是对于像Qt这样的大型库来说,这样做显然是一个更大的任务。我想总会有一些皱纹(比如你发现的那些)从未完全解决过。