2012-09-10 3 views
7

Il existe un programme simple python3:python3 super ne fonctionne pas avec les classes 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) Lorsque la classe Foo hérite de QtCore.QObject et nous obtenons Bar:

(<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) Lorsque la classe Foo hérite de FakeQObject et nous obtenons Bar:

(<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 question est: pourquoi dans le a) cas, Bar init est pas appelé?

J'ai trouvé une question similaire ici pyQt4 and inheritance mais il n'y a pas de bonnes réponses.

Merci d'avance!

+4

Je suppose que c'est parce que 'QtCore.QObject' n'utilise pas le super.'init__' coopératif. BTW, en Python 3, vous n'avez pas besoin de 'super (Foo, self)'; 'super()' devrait être suffisant. – nneonneo

+0

Oui, mais le site PyQt http://www.riverbankcomputing.co.uk/static/Docs/PyQt4/html/gotchas.html dit: "Dans les versions de PyQt antérieures à la version 4.5, il y avait des restrictions sur l'utilisation de super avec Classes PyQt: ces restrictions ne s'appliquent plus aux versions 4.5 et ultérieures. " Donc, c'est un bug de PyQt, n'est-ce pas? – vitvlkv

+0

Merci pour super() sans params, ne le savais pas .. – vitvlkv

Répondre

3

Avec @nneonneo je soupçonne également que QtCore.QObject n'utilise pas la coopérative super.__init__. Si c'était le cas, vous n'auriez pas ce problème.

Cependant, vous devez être conscient que, à un moment donné une des classes de base ne peut pas utiliser super coopérative car object aura pas la méthode. Considérez:

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

et la sortie:

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' 

Donc, quelle que soit la classe va être la fin de la ligne doit pas appeler super. Comme il existe d'autres méthodes Qt que vous pourriez vouloir remplacer, cela signifie que la classe Qt doit être la dernière dans l'en-tête de la classe. En n'ayant pas __init__ utiliser super coopératif, même si elle pourrait, Qt évite les bugs plus bas quand une autre méthode est surchargée.

Questions connexes