2013-12-09 9 views
5

Mam klasę okna dialogowego, która dziedziczy klasę python-generowaną przez pyside-uic, ale moim problemem jest to, że nie można jej rozszerzyć o dodanie innej klasy bazowej.PySide, PysideUIC i wiele dziedziczenia

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_()) 

Kiedy próbuję przedłużyć MainDialog z Worker, super nie nazywają Worker „s __init__ i dlg.data druku nie dlatego, że "AttributeError: 'MainDialog' obiekt ma bez atrybutu 'dane'"

Moja jedyna praca wydaje się ignorować super i wywoływać ręcznie każdy __init__.

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

Czy to moje jedyne rozwiązanie?

To jest dla Pythona 2.7.

+0

Jeśli chodzi o moje doświadczenie jest zaniepokojony, 'super()' nie działa z owijarki PySide do Qt, i nie wierzę, że PyQt tu jest inaczej. Dlatego ręczne wywoływanie '__init__'s może być twoim jedynym sposobem. Tylko pamiętaj, aby unikać (lub obejść) diamentowych spadków. – quazgar

Odpowiedz

1

Wielokrotne dziedziczenie jest trudne w python. Klasy, które dziedziczysz, nie mogą mieć żadnych konfliktów, jeśli chcesz, aby działały idealnie. W większości przypadków dziedziczenie wielokrotne z pyside powoduje konflikt, ponieważ wszystko dziedziczy QObject, dając identyczne zmienne i metody. Python nie wie, który dziedziczyć. Obraz jest kolejnym obszarem konfliktu. Inną kwestią do rozważenia jest kolejność dziedziczenia. Wierzę, że python próbuje dziedziczenia i init od lewej do prawej. Więc jeśli chcesz tylko metodę init dla QtGui.QDialog i Worker (Ui_Dialog prawdopodobnie będzie konfliktować), to możesz spróbować.

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

W pytonie 3 można wywołać metodę super nieco inaczej.

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

Wierzę, że sposób wywoływania init dla 2.7 jest poprawnym sposobem robienia rzeczy. Pytania podobne do tego są wszędzie. Jest to powszechny problem znany jako Diamond problem. Python super method and calling alternatives może wyjaśnić pewne rzeczy nieco więcej.

+0

Należy jednak zauważyć, że 'super()' działa tylko tak, jak zapowiedział, jeśli przodek (przodki) implementuje konstruktory odpowiednio (np. Akceptując '** słowa kluczowe' i ​​przesyłając je do następnego' super() ').Wydaje się, że nie ma to miejsca w przypadku wrapperów PySide klas Qt. – quazgar

1

Bądź Worker pierwsza podstawa klasy:

class MainDialog(Worker, QtGui.QDialog, Ui_Dialog) 

ten będzie nadal prowadzić MainDialog.__init__ nazywany jest pierwszy, a następnie Worker.__init__ (które można zobaczyć jeśli dodać kilka sprawozdań z tuszem). Ale nadal będziesz mieć dostęp do atrybutu data z poziomu MainDialog.__init__.

Klasa Ui_Dialog naprawdę nie figuruje w żadnej z tego, ponieważ jest to tylko zwykła klasa pyton dziedziczenie z object i nie zawsze zadzwonić super. Więc może pójść w dowolne miejsce w kolejności bazowej.

Oczywiście, jeśli robisz to w ten sposób, będziesz musiał uważać, aby nie odrywać żadnych metod od innych klas bazowych w klasie Worker - ale i tak już miałeś ten "problem" (tylko w innej kolejności).