¿Por qué se usa tanto el super en PySide / PyQt?

Versión corta (tl; dr)

Estoy aprendiendo PySide, y la mayoría de los tutoriales en línea usan super para inicializar los elementos de la interfaz de usuario. ¿Es esto importante (es decir, más escalable) o es una cuestión de gusto?

Aclaración : como aclaro más en la versión detallada, este no es otro hilo genérico que pregunta cuándo usar super (esto se ha hecho antes). Más bien, dado el número de tutoriales de PySide que usan super lugar de .__init__ , ¿estoy tratando de averiguar si usar super es estándar en las aplicaciones de PySide? Si es así, ¿es porque las circunstancias en super se llama a super (que involucran la resolución de herencias) surgen mucho específicamente en el uso de PySide / PyQt? O es una cuestión de gusto.

Versión detallada

Soy nuevo en Python y actualmente estoy aprendiendo PySide utilizando el tutorial de Zets ( http://zetcode.com/gui/pysidetutorial/firstprograms/ ). El segundo ejemplo en el tutorial incluye:

 from PySide import QtGui class Example(QtGui.QWidget): def __init__(self): super(Example, self).__init__() self.initUI() def initUI(self): self.setGeometry(300,300,250,150) self.setWindowTitle("PySide 101: Window the First!") self.show() app=QtGui.QApplication(sys.argv) ex=Example() sys.exit(app.exec_()) 

Esto funciona bien, pero nunca he usado super . Por lo tanto, reescribí el código anterior, reemplazando exitosamente a super con una invocación explícita más estándar de la clase padre:

 QtGui.QWidget.__init__(self) 

Pero a medida que busco tutoriales de PySide en la web (por ejemplo, http://qt-project.org/wiki/PySide-Newbie-Tutorials ), todos incluyen llamadas a super . Mi pregunta es: ¿debo usar super para scripts de PySide?

Parece que super parece ser más útil cuando tienes diamantes de herencia, que tiende a resolver instancias de herencia múltiple de una manera razonable. ¿Se usa mucho super con PySide porque hay una preponderancia de casos de tales diamantes que enfrentaré con ejemplos complicados más realistas? [Edición: No: vea mi respuesta a continuación.]

¿Por qué estoy preguntando? ¿Por qué no usar simplemente super y terminar con eso?

Lo pregunto porque el libro que estoy usando para aprender Python (Learning Python, por Lutz) gasta más de 20 páginas sobre el tema de las super , y advierte explícitamente en contra de su uso . Sugiere que los nuevos usuarios de Python opten por la ruta más tradicional y explícita antes de jugar con ella (p. Ej., Consulte la página 832 y las páginas 1041-1064 de Learning Python, 5ta edición). Básicamente, lo pinta como un estilo no piónico, arcano, que rara vez se necesita realmente, que debe tratar con mucha precaución al comenzar, y cree que es un uso excesivo por parte de usuarios experimentados.

Además, al observar el código fuente de dos proyectos principales basados ​​en PySide / PyQt (Spyder y pyqtgraph), ninguno usa super . One (Spyder) le dice explícitamente a los colaboradores que eviten usarlo por razones de compatibilidad ( http://code.google.com/p/spyderlib/wiki/NoteForContributors ).

Tenga en cuenta que me vinculo a una publicación estrechamente relacionada que se encuentra a continuación, pero en la respuesta se analiza de manera más general cuándo querría usar super (cuando tenga herencia múltiple). Mi pregunta es si PySide scripting justifica, o incluso requiere, el uso de super a largo plazo, o si es más Pythonic, y mejor por razones de compatibilidad, para nombrar explícitamente las clases primarias. ¿O es una cuestión de gusto?

Si está mal visto (como sugiere mi libro para principiantes), ¿por qué es tan ubicuo en los tutoriales de PySide dirigidos a los principiantes? Si hay alguna diferencia, parece que las personas que escriben estos tutoriales son progtwigdores Java experimentados o que atienden a dichos progtwigdores. Yo no soy.

Temas relacionados

http://www.riverbankcomputing.com/pipermail/pyqt/2008-January/018320.html

Diferentes formas de usar __init__ para PyQt4

Entendiendo Python super () con __init __ () métodos

Hm, linda. Pero IMO solo está relacionado con Qt / PySide.

Primero, ¿en qué se diferencian estos dos? Si tiene una herencia simple (tal vez sin contar los “mixins”), entonces no hay diferencia en el comportamiento. Sigue habiendo una diferencia estética: no es necesario que vuelva a nombrar su clase base, pero sí tiene que nombrar la misma clase.

Las diferencias comienzan cuando tienes herencia múltiple. Entonces una cadena de super() llama a esta jerarquía:

  A / \ XY \ / Z 

Puede proceder fácilmente así a través de llamadas super() :

  A \ X --- Y \ Z 

sin la necesidad de que X e Y se conozcan. Esto se relaciona con el concepto de orden de resolución de métodos que permite un estilo de progtwigción llamado “herencia múltiple cooperativa” en los documentos de Python .

Si hay un método Foo e implementaciones en X e Y de ese método construidas sobre la implementación de A, entonces Z puede confiar fácilmente en X e Y sin que se conozcan entre sí. Esto, sin embargo, tiene una condición previa importante: Foo tiene la misma firma (o al menos [compatible]) en cada clase, según lo especificado por la interfaz de A donde está definida inicialmente.

El método __init__ es especial: técnicamente funciona de la misma manera con super , pero! pero (la mayoría de las veces) para las subclases tiene una firma totalmente diferente. Si la subclase ‘ __init__ ve diferente, entonces super no le dará nada por encima de la llamada básica explícita porque de todos modos no puede usar la multitarea cooperativa.

Nota: Python es muy atípico a este respecto: en la mayoría de los lenguajes OO, los constructores pertenecen a la clase, en lugar de las instancias; en otras palabras, la mayoría de los idiomas se basan en sus equivalentes de __new__ y no tienen __init__ en absoluto.

Nota 2: Nunca he visto ningún código real que dependa de la herencia múltiple cooperativa. (La sola herencia fácilmente hace suficientes espaguetis para mí ;-))

Además, algunas buenas lecturas:

  • Método de resolución de orden – de qué se trata
  • El Super de Python es ingenioso, pero no puedes usarlo

El

No hay nada de malo en instanciar las clases para padres de la manera tradicional, y hay algunas cosas que se pueden decir a favor. Dicho esto, el uso de super simplifica la creación de subclases, y las modificaciones futuras del código PySide de uno, y la gente parece haberse aferrado a esta última como el factor primordial. Esto no es específico de Pyside, sino de la progtwigción orientada a objetos en Python en general (como se señala en la excelente respuesta de Kos).

El potencial para simplificar la modificación del código viene porque dentro de PySide es necesario que las cosas funcionen para definir subclases basadas en otros objetos QtGui (por ejemplo, QtQui.QMainWindow y QtGui.QWidget ). Además, las personas tienden a jugar con sus clases para padres lo suficiente como para que parezca más fácil simplemente usar super , para que usted no tenga que actualizar su método __init__ cada vez que cambie de padres.

Por lo tanto, no se trata de usar super para ayudar a resolver casos de herencia múltiple, el caso en el que la mayoría de las personas está de acuerdo en que probablemente sea el más adecuado. Más bien, es una cuestión de hacer menos trabajo dentro de __init__ en caso de que su clase padre cambie en el futuro.

Aquí están las respuestas de cada autor, quienes escribieron lo que considero que son buenos tutoriales de PySide:

Autor 1:

Creo que es cuestión de gustos. Tutoriales anteriores (PyQt y PySide) utilizados. Inicia y luego me cambié a super (). Personalmente prefiero super ().

Autor 2:

La razón por la que la gente usa super en lugar de. init (…) es evitar hacer cambios si cambia lo que es la clase principal, por ejemplo, si cambia de QVBoxLayout a QHBoxLayout, solo tiene que cambiarlo en la línea de definición de clase, en lugar de hacerlo también en el método init .

Así que ahí lo tienen. No estos beneficios no son realmente específicos para PySide, sino para escribir subclases / herencia de forma más general.

No estoy seguro de lo que diría Lutz, que parece muy reacio a respaldar el uso de super (tal vez el uso de super viola la máxima de ‘Explícita es mejor que implícita’).

Actualizar cuatro años después
En retrospectiva, este debate ha terminado y esta pregunta es casi extraña (esta fue mi primera pregunta en SO). Mientras que solía haber un debate sobre el uso de super , estos debates se han terminado. Especialmente en Python 3 super ha demostrado su conveniencia y solo hace que su código sea más fácil de mantener. Debido a que en el marco Qt / Pyside / PyQt, el uso de la herencia de clases Qt más abstractas es ubicuo, esta no es una característica pequeña. Claro, tendrás que tener cuidado cuando tengas celosías locas de la herencia, pero francamente desde que hice esta pregunta, literalmente nunca me he encontrado con este problema, y ​​actualmente uso super en todo mi código. Podría decirse que viola la máxima de “lo explícito es mejor que lo implícito”, pero “lo simple es mejor que lo complejo” y la “pureza de lo práctico” son los factores primordiales aquí (el aspecto práctico aquí es “conteos de mantenibilidad”).