Die folgende Verwendung von super()
löst einen TypeError aus: Warum?
>>> from HTMLParser import HTMLParser
>>> class TextParser(HTMLParser):
... def __init__(self):
... super(TextParser, self).__init__()
... self.all_data = []
...
>>> TextParser()
(...)
TypeError: must be type, not classobj
Bei StackOverflow gibt es eine ähnliche Frage: Python super () löst TypeError aus , wobei der Fehler durch die Tatsache erklärt wird, dass die Benutzerklasse keine Klasse neuen Stils ist. Die obige Klasse ist jedoch eine Klasse neuen Stils, da sie erbt von object
:
>>> isinstance(HTMLParser(), object)
True
Was vermisse ich? Wie kann ich super()
hier verwenden?
Verwenden HTMLParser.__init__(self)
statt super(TextParser, self).__init__()
würde funktionieren, aber ich würde gerne den TypeError verstehen.
PS: Joachim wies darauf hin, dass es nicht gleichbedeutend ist, eine Instanz einer Klasse neuen Stils zu sein object
. Ich habe das Gegenteil oft gelesen, daher meine Verwirrung (Beispiel für einen neuen Klasseninstanztest basierend auf dem object
Instanztest: https://stackoverflow.com/revisions/2655651/3 ).
quelle
super.__doc__
nichts über alten oder neuen Stil erwähnt!super()
nur für Klassen (und Objekte) neuen Stils funktioniert, wird im HTML-Dokument ( docs.python.org/library/functions.html#super ) erwähnt.Antworten:
In Ordnung, es ist das übliche "
super()
kann nicht mit einer Klasse alten Stils verwendet werden".Der wichtige Punkt ist jedoch, dass der richtige Test für "Ist dies eine Instanz neuen Stils (dh ein Objekt)?" ist
und nicht (wie in der Frage):
Für Klassen lautet der richtige Test "Ist dies eine Klasse neuen Stils?":
Der entscheidende Punkt ist, dass bei Klassen alten Stils die Klasse einer Instanz und ihr Typ unterschiedlich sind. Hier
OldStyle().__class__
istOldStyle
, was nicht von nicht erbenobject
, währendtype(OldStyle())
die istinstance
Art, die sich aus erbenobject
. Grundsätzlich erstellt eine Klasse im alten Stil nur Objekte vom Typinstance
(während eine Klasse im neuen Stil Objekte erstellt, deren Typ die Klasse selbst ist). Dies ist wahrscheinlich der Grund, warum die InstanzOldStyle()
eineobject
: ihretype()
erbt vonobject
(die Tatsache, dass ihre Klasse nicht erbt vonobject
nicht zählt: Klassen alten Stils konstruieren lediglich neue Objekte vom Typinstance
). Teilreferenz:https://stackoverflow.com/a/9699961/42973 .PS: Der Unterschied zwischen einer Klasse neuen Stils und einer Klasse alten Stils kann auch gesehen werden mit:
(Klassen alten Stils sind keine Typen, daher können sie nicht der Typ ihrer Instanzen sein.)
quelle
(Oldstyle().__class__ is Oldstyle)
istTrue
OldStyle().__class__
geht darum zu zeigen, wie man testet, ob ein Objekt (OldStyle()
) aus einer Klasse alten Stils stammt. Wenn man nur Klassen neuen Stils im Auge hat, könnte man versucht sein,isinstance(OldStyle(), object)
stattdessen den Test mit zu machen.object
, was Sie per Proxy verarscht .super () kann nur in Klassen neuen Stils verwendet werden. Dies bedeutet, dass die Stammklasse von der Klasse 'object' erben muss.
Zum Beispiel muss die Spitzenklasse so sein:
nicht
Die Lösung besteht also darin, die init- Methode des Elternteils wie folgt direkt aufzurufen :
quelle
self
Parameter imHTMLParser.__init__()
Aufruf falsch ist .Sie können auch verwenden
class TextParser(HTMLParser, object):
. Dies machtTextParser
eine Klasse neuen Stils undsuper()
kann verwendet werden.quelle
Das Problem ist, dass man als Vorfahr einen
super
brauchtobject
:Bei näherer Betrachtung findet man:
Aber:
Die Lösung für Ihr Problem wäre also, sowohl vom Objekt als auch vom HTMLParser zu erben. Stellen Sie jedoch sicher, dass das Objekt in den Klassen MRO an letzter Stelle steht:
quelle
type(myclass)
, ist es auch wichtig, obmyclass
vom Objekt geerbt wird (dh obisinstance(myclass, object)
es wahr ist - es ist falsch).Wenn Sie sich den Vererbungsbaum (in Version 2.6) ansehen,
HTMLParser
erbt er, vonSGMLParser
dem erbt, vonParserBase
dem nicht erbtobject
. Dh HTMLParser ist eine alte Klasse.Über Ihre Überprüfung mit habe
isinstance
ich einen kurzen Test in ipython durchgeführt:Selbst wenn eine Klasse eine Klasse alten Stils ist, ist sie immer noch eine Instanz von
object
.quelle
isinstance(A(), object)
, nichtisinstance(A, object)
nein? Mit letzterem testen Sie , ob die KlasseA
eine istobject
, während die Frage, ob Instanzen vonA
sindobject
, nicht wahr?issubclass(HTMLParser, object)
, der False zurückgibt.Die richtige Vorgehensweise ist in den Klassen alten Stils, die nicht von 'object' erben, wie folgt.
quelle
A
, in der ein Status gespeichert ist.FWIW und obwohl ich kein Python-Guru bin, bin ich damit durchgekommen
Ich habe gerade die Analyseergebnisse nach Bedarf zurückbekommen.
quelle