super() falla con error: TypeError "el argumento 1 debe ser tipo, no classobj" cuando el padre no hereda del objeto
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)
|
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.
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)
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)
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__ = type
atributo en la parte superior de mi programa y funcionó.
__metaclass__
: Facilita la transición de clases de estilo antiguo a clases de estilo nuevo.