Python super () genera TypeError


109

En Python 2.5, el siguiente código genera un TypeError:

>>> class X:
      def a(self):
        print "a"

>>> class Y(X):
      def a(self):
        super(Y,self).a()
        print "b"

>>> c = Y()
>>> c.a()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 3, in a
TypeError: super() argument 1 must be type, not classobj

Si reemplazo el class Xcon class X(object), funcionará. ¿Cuál es la explicación de esto?


3
su "sin embargo, reemplazo la clase X con la clase X (objeto)" solucionó mi problema! gracias
AliBZ

Respuestas:


132

La razón es que super()solo opera en clases de estilo nuevo , lo que en la serie 2.x significa que se extiende desde object:

>>> class X(object):
        def a(self):
            print 'a'

>>> class Y(X):
        def a(self):
            super(Y, self).a()
            print 'b'

>>> c = Y()
>>> c.a()
a
b

4
¿De qué versión de Python se convirtió en el comportamiento predeterminado?
Geo

6
2.2 fue cuando se introdujeron las clases de nuevo estilo, 3.0 es donde se convirtieron en las predeterminadas.
Cody Brocious

7
@tsunami si quieres llegar a la superclase, haz "Xa (yo)"
James Brady

Creo que me has malentendido . Tríptico. Recuerdo que estaba usando una versión de Python menor que 3.0, y no dije específicamente que mi clase hereda de Object, y la llamada a super funcionó. ¿Quizás es el comportamiento predeterminado de 2.6? Solo digo :)
Geo

Alabaster, realmente no hay necesidad de eso. Las clases de nuevo estilo tienen una gran cantidad de beneficios, no solo excelentes. No se deben promover las formas antiguas.
Cody Brocious

14

Además, no use super () a menos que sea necesario. No es lo "correcto" de propósito general que se puede hacer con las clases de estilo nuevo que usted pueda sospechar.

Hay momentos en los que espera una herencia múltiple y posiblemente la desee, pero hasta que conozca los detalles complicados del MRO, es mejor dejarlo en paz y atenerse a:

 X.a(self)

2
¿Es eso correcto porque en mis 6 meses de Python / Django he estado usando super como "lo correcto en general"?
philgo20

1
Bueno, no te perjudica la herencia única en sí misma (excepto que es un poco más lenta), pero tampoco te da nada por sí sola. Debe diseñar cualquier método que necesite heredar de forma múltiple (más notablemente __init__) para pasar argumentos de una manera limpia y sensata, de lo contrario obtendrá TypeErrors o problemas de depuración peores cuando alguien intente heredar de manera múltiple usando su clase. A menos que realmente haya diseñado para admitir MI de esta manera (lo cual es bastante complicado), probablemente sea mejor evitar la implicación de superque el método es seguro para MI.
Bobince

3

En caso de que ninguna de las respuestas anteriores lo mencione claramente. Su clase padre necesita heredar de "objeto", que esencialmente lo convertiría en una nueva clase de estilo.

# python 3.x:
class ClassName(object): # This is a new style class
    pass

class ClassName: # This is also a new style class ( implicit inheritance from object )
    pass

# Python 2.x:
class ClassName(object): # This is a new style class
    pass

class ClassName:         # This is a old style class
    pass

Lo siento, pero en Python 3.x su segundo ejemplo (herencia implícita) no funciona realmente en el contexto del problema mencionado.
sophros

1

Probé los distintos métodos Xa (); sin embargo, parecen requerir una instancia de X para realizar un (), así que hice X (). a (self), que parece más completo que las respuestas anteriores, al menos para las aplicaciones que he encontrado. No parece ser una buena manera de manejar el problema ya que hay una construcción y destrucción innecesarias, pero funciona bien.

Mi aplicación específica fue el módulo cmd.Cmd de Python, que evidentemente no es un objeto NewStyle por alguna razón.

Resultado final:

X().a(self)
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.