2009-11-11 9 views
112

Me sale un error que no puedo entender. ¿Alguna pista de lo que está mal con mi código de muestra?super() falla con el error: TypeError "argumento 1 debe ser tipo, no classobj"

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

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

print C().meth(1) 

me dieron el código de prueba de muestra de ayuda de 'super' método integrado. La clase "C" es el

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 

FYI, aquí está la ayuda (super) de pitón en sí:

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) 
| 
+0

posible duplicado de [python super() provoca TypeError! ¿Por qué?] (Http://stackoverflow.com/questions/489269/python-super-raises-typeerror-why) – user

+1

Meth ?? Es ese un término de programación, o ... ¿sabes? Por favor aclara – Cplusplusplus

+2

@Cplusplusplus: probablemente representa Método ;-) – ShadowFlame

Respuesta

197

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

class B(object): 

y funcionará.

super() y todas las cosas de subclase/superclase solo funcionan con clases de estilo nuevo. Te recomiendo que te acostumbres a escribir siempre (object) en cualquier definición de clase para asegurarte de que sea una clase de nuevo estilo.

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

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

Pruebe lo siguiente para ver por sí 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 son de nuevo cuño. Aún puede usar la sintaxis de las clases antiguas pero obtiene una clase de estilo nuevo. Entonces, en Python 3.x no tendrás este problema.

+0

interesante, he encontrado este problema exacto funcionamiento bottle.py (http://bottlepy.org), que arroja un error similar (TypeError: debe ser de tipo, no classobj) que se ejecuta en Py27 pero no Py33. – bootload

+0

En Python 3.x, no hay más clases "antiguas". El código que utiliza la declaración de "estilo antiguo" todavía declara una clase de "estilo nuevo", por lo que este error no puede ocurrir en Python 3.x. – steveha

+0

¿Qué pasa si la clase B no está disponible para editar? –

92

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) 
+2

'objeto' ya que la segunda clase para padres es un buen truco. –

+7

No pude evitar dejar un comentario, este debe ser aceptado como respuesta "estándar". – hylepo

+4

Para futuros googlers trabajados en Python 2.6: ¡esta es la respuesta que probablemente quieras! Cuando no puede cambiar la clase base (por ejemplo, está subclasificando una clase de biblioteca estándar), este cambio a su propia clase corrige super(). – CoreDumpError

10

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

creo que la versión de Python es 2.X, el super funcionaría cuando se añade este código

__metaclass__ = type 

lo que el código está

__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) 
2

También se enfrentó con el tema publicado cuando usado python 2.7. Está funcionando muy bien con python 3.4

Para que funcione en python 2.7 He agregado el atributo __metaclass__ = type en la parte superior de mi programa y funcionó.

__metaclass__: Facilita la transición de las clases antiguas a las nuevas.

Cuestiones relacionadas