2012-09-10 14 views
7

C'è un programma semplice in python3:python3 eccellente non funziona con le classi PyQt

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) Quando la classe Foo eredita da QtCore.QObject e Bar otteniamo:

(<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) Quando la classe Foo eredita da FakeQObject e Bar otteniamo:

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

la domanda è: perché nel caso a), Bar init non si chiama?

Ho trovato una domanda simile qui pyQt4 and inheritance ma non ci sono buone risposte.

Grazie in anticipo!

+4

Sospetto che sia perché 'QtCore.QObject' non utilizza la cooperativa super .__init__'. BTW, in Python 3, non hai bisogno di 'super (Foo, self)'; 'super()' dovrebbe essere sufficiente. – nneonneo

+0

Sì, ma il sito PyQt http://www.riverbankcomputing.co.uk/static/Docs/PyQt4/html/gotchas.html dice: "Nelle versioni di PyQt precedenti alla v4.5 c'erano restrizioni sull'uso di Super con Classi PyQt. Queste restrizioni non si applicano più con la v4.5 e successive. " Quindi, questo è un bug di PyQt, non è vero? – vitvlkv

+0

Grazie per super() senza parametri, non lo sapevamo .. – vitvlkv

risposta

3

Insieme a @nneonneo ho anche il sospetto che QtCore.QObject non utilizzi la cooperativa super.__init__. Se lo facesse, non avresti questo problema.

Tuttavia, si dovrebbe essere consapevoli del fatto che ad un certo punto una delle classi di base non può usare cooperativa eccellente perché object non avrà il metodo. Considerate:

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')) 

e l'uscita:

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' 

Quindi, a seconda di quale classe sta per essere il finale della linea ha bisogno di non chiamare super. Perché ci sono altri metodi Qt che potresti voler sovrascrivere, che impongono che la classe Qt debba essere l'ultima nell'intestazione della classe. Non avendo __init__ l'uso cooperativo super, anche se potesse, Qt evita i bug più in basso quando qualche altro metodo viene sovrascritto.

Problemi correlati