2013-12-09 71 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類的其他基類中剔除任何方法 - 但是你已經有了這個「問題」(只是以不同的順序) )。