2013-12-09 44 views
5

我有一个对话框类继承了pyside-uic生成的python类,但我的问题是它无法扩展我添加另一个基类。PySide,PysideUIC和多继承

import sys 
from PySide import QtGui 
from mi_ui import Ui_Dialog 

class Worker(object): 
    def __init__(self): 
     super(Worker, self).__init__() 
     self.data = 1 

class MainDialog(QtGui.QDialog, Ui_Dialog, Worker): 
    def __init__(self): 
     super(MainDialog, self).__init__() 
     self.setupUi(self) 

if __name__ == '__main__': 
    app = QtGui.QApplication(sys.argv) 
    dlg = MainDialog() 
    print dlg.data 
    dlg.show() 

    sys.exit(app.exec_()) 

当我尝试用Worker延长MainDialog,超级不叫Worker__init__因为打印dlg.data失败‘AttributeError的:‘MainDialog’对象有没有属性‘数据’’

我唯一的工作似乎忽略超级,并手动调用每个__init__

QtGui.QDialog.__init__(self) 
Worker.__init__(self) 

这是我唯一的解决方案吗?

这是针对Python 2.7的。

+0

就我的经验而言,'super()'不适用于Qt的PySide包装器,我不认为PyQt在这里有什么不同。所以手动调用'__init__'可能是你唯一的方法。只要确保避免(或绕过)菱形遗产。 – quazgar

回答

1

python中的多继承很棘手。如果您希望它完美地工作,那么您继承的类不会有任何冲突。在大多数情况下,使用pyside进行多重继承确实会导致冲突,因为一切都会继承QObject,并提供相同的变量和方法。 Python不知道要继承哪一个。这幅画是另一个冲突的领域。另一件要考虑的是继承的顺序。我相信python会尝试从左到右的继承和init。所以,如果你只想为QtGui.QDialog和Worker(Ui_Dialog可能会发生冲突)的init方法,那么你可能想尝试。

class MainDialog(QtGui.QDialog, Worker, Ui_Dialog): 

在python 3中,你可以调用super方法有点不同。

class MainDialog(QtGui.QDialog, Worker, Ui_Dialog): 
    super().__init__() 

我相信你调用2.7的init方法是正确的做事方式。类似这样的问题遍布全球。这是一个常见的问题,被称为Diamond problemPython super method and calling alternatives可能会解释一些事情。

+0

但是请注意,如果祖先适当地实现它们的构造函数(比如接受'**关键字'并将它转发到下一个'super()'),'super()'只能像宣布的那样工作。对于Qt类的PySide包装来说,这似乎不是这种情况。 – quazgar

1

Worker最初的基类:

class MainDialog(Worker, QtGui.QDialog, Ui_Dialog) 

这仍然将导致MainDialog.__init__第一次被调用,那么Worker.__init__(如果你添加一些打印报表时可以看到)。但是您仍然可以从MainDialog.__init__中访问data属性。

Ui_Dialog这个类并没有真正体现在这个中,因为它只是一个普通的python类,继承自object,并且永远不会调用super。因此,它可以在基地级订单中到达任何你喜欢的地方。很显然,如果你用这种方式做事情,你必须注意不要从Worker类的其他基类中剔除任何方法 - 但是你已经有了这个“问题”(只是以不同的顺序) )。