L'utilisation suivante de super()
déclenche une TypeError: pourquoi?
>>> from HTMLParser import HTMLParser
>>> class TextParser(HTMLParser):
... def __init__(self):
... super(TextParser, self).__init__()
... self.all_data = []
...
>>> TextParser()
(...)
TypeError: must be type, not classobj
Il y a une question similaire sur StackOverflow: Python super () déclenche TypeError , où l'erreur est expliquée par le fait que la classe utilisateur n'est pas une classe de nouveau style. Cependant, la classe ci-dessus est une classe de nouveau style, car elle hérite de object
:
>>> isinstance(HTMLParser(), object)
True
Qu'est-ce que je rate? Comment puis-je utiliser super()
, ici?
Utiliser HTMLParser.__init__(self)
au lieu de super(TextParser, self).__init__()
fonctionnerait, mais je voudrais comprendre le TypeError.
PS: Joachim a souligné qu'être une instance de classe de nouveau style n'est pas équivalent à être un object
. J'ai lu l'opposé plusieurs fois, d'où ma confusion (exemple de test d'instance de classe de nouveau style basé sur le object
test d'instance: https://stackoverflow.com/revisions/2655651/3 ).
la source
super.__doc__
ne mentionne rien de l'ancien contre le nouveau style!super()
ne fonctionne que pour les classes (et les objets) de nouveau style est mentionné dans le document HTML ( docs.python.org/library/functions.html#super ).Réponses:
D'accord, c'est l'habituel "
super()
ne peut pas être utilisé avec une classe à l'ancienne".Cependant, le point important est que le test correct pour "est-ce une instance de nouveau style (c'est-à-dire un objet)?" est
et non (comme dans la question):
Pour les classes , le test correct "est-ce une classe de nouveau style" est:
Le point crucial est qu'avec les classes à l'ancienne, la classe d'une instance et son type sont distincts. , Ici
OldStyle().__class__
estOldStyle
, qui ne hérite deobject
, touttype(OldStyle())
est leinstance
type, qui ne hérite deobject
. Fondamentalement, une classe à l'ancienne crée simplement des objets de typeinstance
(alors qu'une classe à nouveau style crée des objets dont le type est la classe elle-même). Ceci est probablement la raison pour laquelle l'instanceOldStyle()
estobject
: sestype()
hérite deobject
(le fait que sa classe ne pas hériter deobject
ne compte pas: les classes de style ancien construisent simplement de nouveaux objets de typeinstance
). Référence partielle:https://stackoverflow.com/a/9699961/42973 .PS: La différence entre une classe de style nouveau et une classe de style ancien peut également être vue avec:
(les classes à l'ancienne ne sont pas des types, elles ne peuvent donc pas être le type de leurs instances).
la source
(Oldstyle().__class__ is Oldstyle)
estTrue
OldStyle().__class__
est de montrer comment tester si un objet (OldStyle()
) provient d'une classe à l'ancienne. Avec seulement des classes de style nouveau à l'esprit, on pourrait être tenté de faire le test avec à laisinstance(OldStyle(), object)
place.object
, ainsi vous vissant par procuration.super () ne peut être utilisé que dans les classes de nouveau style, ce qui signifie que la classe racine doit hériter de la classe 'object'.
Par exemple, la classe supérieure doit être comme ceci:
ne pas
Donc, la solution est d'appeler directement la méthode init du parent , comme ceci:
la source
self
paramètre dans l'HTMLParser.__init__()
appel.Vous pouvez également utiliser
class TextParser(HTMLParser, object):
. Cela créeTextParser
une classe de nouveau style etsuper()
peut être utilisé.la source
Le problème est qu'il a
super
besoin d'object
un ancêtre:En y regardant de plus près, on constate:
Mais:
Ainsi, la solution à votre problème serait d'hériter de l'objet ainsi que de HTMLParser. Mais assurez-vous que l'objet arrive en dernier dans les classes MRO:
la source
type(myclass)
, ce qui importe est de savoir simyclass
hériter de l'objet (c'est-à-dire siisinstance(myclass, object)
c'est vrai, c'est faux).Si vous regardez l'arbre d'héritage (dans la version 2.6),
HTMLParser
hérite deSGMLParser
qui hérite deParserBase
qui n'hérite pas deobject
. Ie HTMLParser est une classe à l'ancienne.À propos de votre vérification avec
isinstance
, j'ai fait un test rapide en ipython:Même si une classe est une classe à l'ancienne, c'est toujours une instance de
object
.la source
isinstance(A(), object)
, nonisinstance(A, object)
, non? Avec ce dernier, vous testez si la classeA
est unobject
, alors que la question est de savoir si les instances deA
sont unobject
, non?issubclass(HTMLParser, object)
, ce qui renvoie Faux.la bonne façon de faire sera comme suit dans les classes à l'ancienne qui n'hérite pas de 'object'
la source
A
qui stocke un état.FWIW et bien que je ne sois pas un gourou de Python, je m'en suis sorti
Je viens de récupérer les résultats de l'analyse au besoin.
la source