2009-10-29 10 views
5

Cuando amplié algunas clases generadas por la herramienta, no me di cuenta de que son clases de estilo antiguo hasta que intenté usar super(). El super() no funciona con las clases de estilo antiguo, así que tengo este error:¿Está bien ampliar las clases de estilo antiguo y nuevo?

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

Por ejemplo, prueba este fragmento:

>>> class A: 
...  def greet(self): 
...   print "A says hi" 
... 
>>> class B(A): 
...  def greet(self): 
...   print "B says hi" 
... 
>>> super(B, B()).greet() 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
TypeError: super() argument 1 must be type, not classobj 

Tenía curiosidad lo que pasaría si me prolongado B desde object también para convertirlo en una nueva clase de estilo, y parecía hacer que super() funcionara.

>>> class B(A, object): 
...  def greet(self): 
...   print "B says hi" 
... 
>>> super(B, B()).greet() 
A says hi 

¿Es esta una solución adecuada o tendré algunas consecuencias no deseadas más adelante?

+2

¿Por qué no se puede cambiar 'clase A 'a' clase A (objeto) '? ¿Qué le impide solucionar la causa raíz y hacer que todo sea nuevo? ¿Por qué crees que una solución alternativa es mejor que una solución? –

+1

La razón es que se genera la clase A (como mencioné al principio, estoy ampliando las clases generadas por la herramienta). Si realizo este cambio, la próxima vez que regenere las clases, se sobrescribirán. – haridsv

Respuesta

1

Si no puede cambiar el generador para generar clases de nuevo estilo, se podría procesar posteriormente el archivo para hacerlos de nuevo cuño:

import re 
pat = re.compile("^(.*class\s+\w+)(:.*)$") 
out_file = open("edited_file.py", "w") 
for line in open("generated_file.py"): 
    m = pat.match(line) 
    if m: 
     line = m.group(1) + "(object)" + m.group(2) + "\n" 
    out_file.write(line) 

out_file.close() 

Si no quieres hacer eso por alguna razón , entonces seguro, adelante y subclase la clase original y object. Que yo sepa, eso debería funcionar bien; su nueva clase será una clase de nuevo estilo.

El libro Python in a Nutshell (por Alex Martelli, publicado por O'Reilly) dice que si declaras una clase con clases base y al menos una de las clases base es de estilo nuevo, siempre será una clase de estilo nuevo . No enumera ninguna advertencia o peligro especial relacionado con esta acción. Creo que eres bueno para ir.

4

Las clases de nuevo estilo se han recomendado en Python desde que se introdujeron en Python 2.2. En Python 3.x, solo las clases de nuevo estilo están disponibles. Por lo tanto, te recomiendo que cambies tus clases a un nuevo estilo.

No tengo conocimiento de ningún problema real que pueda tener a causa de esto. En su mayor parte, las clases de nuevo estilo simplemente traen nuevas funciones, como super() que realmente funcionan. Si tiene un código que depende de la semántica de las clases antiguas de manera complicada, ese código, por supuesto, se romperá. (El único ejemplo que me viene a la mente es el famoso Borg pattern del famoso Alex Martelli.)

Here es un enlace al manual de referencia de Python para una discusión de las nuevas clases de estilo vs. clases antiguas ("clásicas") . Y here es un enlace al ensayo clásico donde Guido van Rossum explica por qué se introdujeron las clases de nuevo estilo.

Uso solo las clases de estilo nuevo en mi código y lo animo a que haga lo mismo.

+0

Gracias por los enlaces interesantes.Vea mis últimos comentarios sobre por qué A es de estilo antiguo. – haridsv

+0

Me disculpo por no haber entendido lo que estaba preguntando; Debo haber estado cansado anoche cuando escribí esto. He escrito una segunda respuesta que es mejor. – steveha

0

No veo ningún problema para mezclar clases clásicas y nuevas, a menos que algunos métodos dependan de la semántica clásica o su base clásica use metaclass (la metaclase de descendencia siempre será una clase de estilo nuevo).

Por otro lado, no veo ninguna razón para utilizar clases clásicas, por lo que es preferible cambiar class A: a class A(object):.

+0

Estoy de acuerdo con usted, sin embargo, se genera la clase A. Para el contexto, la herramienta de la que estoy hablando es el paquete ZSI que proporciona las herramientas wsdl2py y wsdl2dispatch. No se han mantenido desde algún momento en 2007, por lo que no estoy seguro de cuándo lo actualizarán para Python 3.0. En este momento, sigo usando 2.6, así que no tengo ningún problema con estas clases generadas. Ni siquiera he visto un paquete más nuevo alternativo para implementar el servidor SOAP. – haridsv

Cuestiones relacionadas