El siguiente uso de super()
plantea un error de tipo: ¿por qué?
>>> from HTMLParser import HTMLParser
>>> class TextParser(HTMLParser):
... def __init__(self):
... super(TextParser, self).__init__()
... self.all_data = []
...
>>> TextParser()
(...)
TypeError: must be type, not classobj
Hay una pregunta similar en StackOverflow: Python super () plantea TypeError , donde el error se explica por el hecho de que la clase de usuario no es una clase de estilo nuevo. Sin embargo, la clase anterior es una clase de nuevo estilo, ya que hereda de object
:
>>> isinstance(HTMLParser(), object)
True
¿Qué me estoy perdiendo? ¿Cómo puedo usar super()
aquí?
Usar en HTMLParser.__init__(self)
lugar de super(TextParser, self).__init__()
funcionaría, pero me gustaría entender el TypeError.
PD: Joachim señaló que ser una instancia de clase de estilo nuevo no es equivalente a ser un object
. Leí lo contrario muchas veces, de ahí mi confusión (ejemplo de prueba de instancia de clase de nuevo estilo basada en object
prueba de instancia: https://stackoverflow.com/revisions/2655651/3 ).
fuente
super.__doc__
no menciona nada sobre el estilo antiguo frente al nuevo!super()
solo funciona para clases (y objetos) de estilo nuevo se menciona en el documento HTML ( docs.python.org/library/functions.html#super ).Respuestas:
Muy bien, es lo habitual "
super()
no se puede usar con una clase de estilo antiguo".Sin embargo, el punto importante es que la prueba correcta para "¿es esta una instancia de nuevo estilo (es decir, un objeto)?" es
y no (como en la pregunta):
Para las clases , la prueba correcta de "es una clase de estilo nuevo" es:
El punto crucial es que con las clases de estilo antiguo, la clase de una instancia y su tipo son distintos. En este caso,
OldStyle().__class__
esOldStyle
que no hereda deobject
, mientras quetype(OldStyle())
es elinstance
tipo, que no heredan deobject
. Básicamente, una clase de estilo antiguo solo crea objetos de tipoinstance
(mientras que una clase de estilo nuevo crea objetos cuyo tipo es la clase misma). Esta es probablemente la razón por la cual la instanciaOldStyle()
esobject
:type()
hereda deobject
(el hecho de que su clase no herede deobject
no cuenta: las clases de estilo antiguo simplemente construyen nuevos objetos de tipoinstance
). Referencia parcial:https://stackoverflow.com/a/9699961/42973 .PD: La diferencia entre una clase de estilo nuevo y una de estilo antiguo también se puede ver con:
(las clases de estilo antiguo no son tipos, por lo que no pueden ser el tipo de sus instancias).
fuente
(Oldstyle().__class__ is Oldstyle)
esTrue
OldStyle().__class__
es mostrar cómo probar si un objeto (OldStyle()
) proviene de una clase de estilo antiguo. Con solo las clases de estilo nuevo en mente, uno podría verse tentado a hacer la pruebaisinstance(OldStyle(), object)
.object
, por lo que te atornilla por proxy.super () solo se puede usar en las clases de estilo nuevo, lo que significa que la clase raíz debe heredar de la clase 'objeto'.
Por ejemplo, la clase superior debe ser así:
no
Entonces, la solución es llamar directamente al método init del padre , de esta manera:
fuente
self
parámetros en laHTMLParser.__init__()
llamada.También puedes usar
class TextParser(HTMLParser, object):
. Esto haceTextParser
una nueva clase de estilo , ysuper()
se puede usar.fuente
El problema es que
super
necesitaobject
un antepasado:En un examen más detallado, uno encuentra:
Pero:
Entonces, la solución a su problema sería heredar del objeto y de HTMLParser. Pero asegúrese de que el objeto venga último en las clases MRO:
fuente
type(myclass)
, lo que importa es simyclass
heredar del objeto (es decir, siisinstance(myclass, object)
es verdadero, es falso).Si observa el árbol de herencia (en la versión 2.6),
HTMLParser
hereda de loSGMLParser
que hereda deParserBase
lo que no heredaobject
. Es decir, HTMLParser es una clase de estilo antiguo.Sobre su verificación con
isinstance
, hice una prueba rápida en ipython:Incluso si una clase es de estilo antiguo, sigue siendo una instancia de
object
.fuente
isinstance(A(), object)
, noisinstance(A, object)
, ¿no? Con este último, está probando si la claseA
es unaobject
, mientras que la pregunta es si las instancias deA
son unaobject
, ¿verdad?issubclass(HTMLParser, object)
, que devuelve False.la forma correcta de hacerlo será la siguiente en las clases de estilo antiguo que no hereda de 'objeto'
fuente
A
que almacena un estado.FWIW y aunque no soy un gurú de Python, me las arreglé con esto
Acabo de recibir los resultados del análisis según sea necesario.
fuente