super() falla con error: TypeError "el argumento 1 debe ser tipo, no classobj" cuando el padre no hereda del objeto

Resuelto Ehsan Foroughi asked hace 14 años • 4 respuestas

Recibo un error que no puedo entender. ¿Alguna pista de qué hay de malo en mi código de muestra?

class B:
    def meth(self, arg):
        print arg

class C(B):
    def meth(self, arg):
        super(C, self).meth(arg)

print C().meth(1)

Obtuve el código de prueba de muestra con la ayuda del método incorporado 'súper'.

Aquí está el error:

Traceback (most recent call last):
  File "./test.py", line 10, in ?
    print C().meth(1)
  File "./test.py", line 8, in meth
    super(C, self).meth(arg)
TypeError: super() argument 1 must be type, not classobj

Para su información, aquí está la ayuda (súper) del propio Python:

Help on class super in module __builtin__:

class super(object)
 |  super(type) -> unbound super object
 |  super(type, obj) -> bound super object; requires isinstance(obj, type)
 |  super(type, type2) -> bound super object; requires issubclass(type2, type)
 |  Typical use to call a cooperative superclass method:
 |  class C(B):
 |      def meth(self, arg):
 |          super(C, self).meth(arg)
 |
Ehsan Foroughi avatar Nov 11 '09 11:11 Ehsan Foroughi
Aceptado

Su problema es que la clase B no está declarada como una clase de "nuevo estilo". Cámbialo así:

class B(object):

y funcionará.

super()y todo el material de subclases/superclases solo funciona con clases de nuevo estilo. Le recomiendo que adquiera el hábito de escribir siempre eso (object)en cualquier definición de clase para asegurarse de que sea una clase de nuevo estilo.

Las clases de estilo antiguo (también conocidas como clases "clásicas") siempre son de tipo classobj; Las clases de nuevo estilo son de tipo type. Es por eso que recibió el mensaje de error que vio:

TypeError: super() argument 1 must be type, not classobj

Pruebe esto para comprobarlo usted mismo:

class OldStyle:
    pass

class NewStyle(object):
    pass

print type(OldStyle)  # prints: <type 'classobj'>

print type(NewStyle) # prints <type 'type'>

Tenga en cuenta que en Python 3.x, todas las clases tienen un estilo nuevo. Aún puedes usar la sintaxis de las clases de estilo antiguo, pero obtendrás una clase de estilo nuevo. Entonces, en Python 3.x no tendrás este problema.

steveha avatar Nov 11 '2009 04:11 steveha

Además, si no puede cambiar la clase B, puede corregir el error utilizando herencia múltiple.

class B:
    def meth(self, arg):
        print arg

class C(B, object):
    def meth(self, arg):
        super(C, self).meth(arg)

print C().meth(1)
frmdstryr avatar Aug 23 '2013 00:08 frmdstryr

Si la versión de Python es 3.X, está bien.

Creo que tu versión de Python es 2.X, el super funcionaría al agregar este código

__metaclass__ = type

entonces el código es

__metaclass__ = type
class B:
    def meth(self, arg):
        print arg
class C(B):
    def meth(self, arg):
        super(C, self).meth(arg)
print C().meth(1)
yanghaogn avatar Aug 05 '2015 01:08 yanghaogn

También me enfrenté al problema publicado cuando usé Python 2.7. Está funcionando muy bien con Python 3.4.

Para que funcione en Python 2.7, agregué el __metaclass__ = typeatributo en la parte superior de mi programa y funcionó.

__metaclass__: Facilita la transición de clases de estilo antiguo a clases de estilo nuevo.

JON avatar Feb 28 '2017 06:02 JON