2012-09-10 13 views
7

Hay un programa simple en python3:python3 súper no funciona con las clases de 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) Cuando la clase Foo hereda de QtCore.QObject y bar obtenemos:

(<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) Cuando la clase Foo hereda de FakeQObject y bar obtenemos:

(<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 pregunta es: ¿por qué en el caso a), Bar init no se llama?

He encontrado una pregunta similar aquí pyQt4 and inheritance pero no hay buenas respuestas.

¡Gracias de antemano!

+4

Sospecho que es porque 'QtCore.QObject' no utiliza la cooperativa super'__init__'. Por cierto, en Python 3, no necesitas 'super (Foo, self)'; 'super()' debería ser suficiente. – nneonneo

+0

Sí, pero el sitio de PyQt http://www.riverbankcomputing.co.uk/static/Docs/PyQt4/html/gotchas.html dice: "En las versiones de PyQt anteriores a la v4.5, había restricciones en el uso de super con Clases de PyQt. Estas restricciones ya no se aplican con v4.5 y posterior ". Entonces, este es un error de PyQt, ¿no es así? – vitvlkv

+0

Gracias por super() sin params, no lo sabía .. – vitvlkv

Respuesta

3

Junto con @nneonneo también sospecho que QtCore.QObject no utiliza la cooperativa super.__init__. Si lo hiciera, no tendrías este problema.

Sin embargo, debe tener en cuenta que en algún punto una de las clases base no puede usar cooperative super porque object no tendrá el método. Considere:

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

y la salida:

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' 

Por lo tanto, lo que la clase va a ser el final de la línea tiene que llamar no super. Debido a que hay otros métodos Qt que puede querer anular, eso dicta que la clase Qt debe ser la última en el encabezado de clase. Al no tener __init__ usar cooperative super, aunque podría, Qt está evitando errores más abajo cuando se anula algún otro método.

Cuestiones relacionadas