2009-10-29 5 views
5

Lorsque j'ai étendu certaines classes générées par un outil, je n'ai pas réalisé qu'il s'agissait de classes de style ancien jusqu'à ce que j'essaie d'utiliser super(). Le super() ne fonctionne pas avec des classes de style ancien, alors je suis cette erreur:Est-il possible d'étendre les anciennes et nouvelles classes de style?

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

Par exemple, essayez cet extrait:

>>> 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 

J'étais curieux de savoir ce qui se passerait si je tendis B de l'objet aussi bien pour en faire une nouvelle classe de style, et il a semblé faire super() travail.

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

Est-ce une solution de contournement appropriée ou aurai-je des conséquences indésirables plus tard?

+2

Pourquoi ne pouvez-vous pas changer 'class A'' 'classe A (objet)'? Qu'est-ce qui vous empêche de réparer la cause première et de tout faire nouveau style? Pourquoi pensez-vous qu'une solution de rechange est meilleure qu'une solution? –

+1

La raison en est que la classe A est générée (comme je l'ai mentionné au début, j'étend les classes générées par l'outil). Si je fais ce changement, la prochaine fois que je régénérerai les classes, elles seront écrasées. – haridsv

Répondre

1

Si vous ne pouvez pas changer le générateur pour générer des classes nouveau style, vous pouvez post-traiter le fichier pour les rendre nouveau style:

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 vous ne voulez pas faire cela pour une raison quelconque , alors bien sûr, allez-y et sous-classe à la fois la classe originale et object. Au meilleur de ma connaissance, cela devrait fonctionner très bien; votre nouvelle classe sera une classe de nouveau style. Le livre Python in a Nutshell (par Alex Martelli, publié par O'Reilly) dit que si vous déclarez une classe avec des classes de base et qu'au moins l'une des classes de base est new-style, ce sera toujours une classe de nouveau style . Il n'indique aucun avertissement ou danger particulier lié à cette action. Je pense que tu es bon à faire.

4

Les classes de style nouveau sont recommandées pour Python depuis qu'elles ont été introduites dans Python 2.2. Dans Python 3.x, seules les nouvelles classes de style sont disponibles. Par conséquent, je vous recommande de changer vos classes à nouveau style.

Je ne suis pas au courant de vrais problèmes que vous pourriez avoir à ce sujet. Pour la plupart, les classes de style nouveau apportent simplement de nouvelles fonctionnalités, telles que super() qui fonctionnent réellement. Si vous avez un code qui repose sur la sémantique des classes à l'ancienne de manière délicate, ce code serait bien sûr rompu. (Le seul exemple qui vient à l'esprit est la célèbre Borg pattern par le célèbre Alex Martelli.)

Here est un lien vers le manuel de référence Python pour une discussion de nouvelles classes de style par rapport à l'ancienne (« classique ») des classes . Et here est un lien vers l'essai classique où Guido van Rossum explique pourquoi les classes de style nouveau ont été introduites. Je n'utilise que des classes de style nouveau dans mon code et je vous encourage à faire de même.

+0

Merci pour les liens intéressants.Voir mes derniers commentaires pour pourquoi A est à l'ancienne. – haridsv

+0

Je m'excuse de ne pas comprendre ce que vous demandiez; J'ai dû être fatigué la nuit dernière quand j'ai écrit ceci. J'ai écrit une deuxième réponse qui est meilleure. – steveha

0

Je ne vois aucun problème à mélanger les classes classiques et celles de style nouveau, à moins que certaines méthodes reposent sur la sémantique classique ou que votre base classique utilise la métaclasse (la métaclasse de la progéniture sera toujours une nouvelle classe). D'autre part, je ne vois aucune raison d'utiliser des classes classiques, donc class A: à class A(object): est préférable.

+0

Je serais d'accord avec vous, cependant, la classe A est générée. Pour le contexte, l'outil dont je parle est le paquet ZSI qui donne les outils wsdl2py et wsdl2dispatch. Ils n'ont pas été entretenus depuis quelque temps en 2007, donc je ne sais pas quand ils vont le mettre à jour pour python 3.0. En ce moment, j'utilise toujours 2.6, donc je n'ai pas de problème avec ces classes générées. Je n'ai même pas vu un autre paquet plus récent pour l'implémentation du serveur SOAP. – haridsv

Questions connexes