O seguinte uso de super()
gera um TypeError: 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
Há uma pergunta semelhante no StackOverflow: Python super () gera TypeError , onde o erro é explicado pelo fato de a classe de usuário não ser uma classe de novo estilo. No entanto, a classe acima é uma classe de novo estilo, pois herda de object
:
>>> isinstance(HTMLParser(), object)
True
o que estou perdendo? Como posso usar super()
aqui?
Usar em HTMLParser.__init__(self)
vez de super(TextParser, self).__init__()
funcionaria, mas eu gostaria de entender o TypeError.
PS: Joachim apontou que ser uma instância de nova classe de estilo não é equivalente a ser uma object
. Eu li o contrário várias vezes, daí a minha confusão (exemplo de teste de instância de classe de novo estilo com base no object
teste de instância: https://stackoverflow.com/revisions/2655651/3 ).
fonte
super.__doc__
não menciona nada sobre o antigo e o novo estilo!super()
funcionar apenas para classes (e objetos) de novo estilo é mencionado no documento HTML ( docs.python.org/library/functions.html#super ).Respostas:
Tudo bem, é o habitual "
super()
não pode ser usado com uma classe de estilo antigo".No entanto, o ponto importante é que o teste correto para "esta é uma instância de novo estilo (ou seja, objeto)?" é
e não (como na pergunta):
Para as classes , o teste "é uma classe de novo estilo" correto é:
O ponto crucial é que, com classes de estilo antigo, a classe de uma instância e seu tipo são distintos. Aqui,
OldStyle().__class__
éOldStyle
, que não herda deobject
, ao mesmo tempotype(OldStyle())
é oinstance
tipo, que não herdamobject
. Basicamente, uma classe de estilo antigo apenas cria objetos do tipoinstance
(enquanto uma classe de estilo novo cria objetos cujo tipo é a própria classe). Provavelmente é por isso que a instânciaOldStyle()
é umaobject
:type()
herda deobject
(o fato de sua classe não herdar deobject
não conta: classes de estilo antigo apenas constroem novos objetos do tipoinstance
). Referência parcial:https://stackoverflow.com/a/9699961/42973 .PS: A diferença entre uma classe de estilo novo e uma classe de estilo antigo também pode ser vista com:
(as classes de estilo antigo não são tipos, portanto, não podem ser o tipo de suas instâncias).
fonte
(Oldstyle().__class__ is Oldstyle)
éTrue
OldStyle().__class__
é mostrar como testar se um objeto (OldStyle()
) vem de uma classe de estilo antigo. Com apenas aulas de estilo novo em mente, pode-se tentar fazer o testeisinstance(OldStyle(), object)
.object
, fazendo com que você seja procurado por proxy.super () pode ser usado apenas nas classes de novo estilo, o que significa que a classe raiz precisa herdar da classe 'objeto'.
Por exemplo, a classe superior precisa ser assim:
não
Portanto, a solução é chamar o método init do pai diretamente, assim:
fonte
self
parâmetro naHTMLParser.__init__()
chamada.Você também pode usar
class TextParser(HTMLParser, object):
. Isso criaTextParser
uma classe de novo estilo esuper()
pode ser usado.fonte
O problema é que
super
precisa deobject
um ancestral:Em um exame mais detalhado, encontra-se:
Mas:
Portanto, a solução para o seu problema seria herdar do objeto e do HTMLParser. Mas verifique se o objeto vem por último nas classes MRO:
fonte
type(myclass)
, o que importa é semyclass
herdar do objeto (ou seja, seisinstance(myclass, object)
é verdadeiro - é falso).Se você olhar para a árvore de herança (na versão 2.6),
HTMLParser
herda daSGMLParser
qual herda daParserBase
qual não herdaobject
. Ou seja, HTMLParser é uma classe de estilo antigo.Sobre a sua verificação
isinstance
, fiz um teste rápido no ipython:Mesmo que uma classe seja de estilo antigo, ainda é uma instância de
object
.fonte
isinstance(A(), object)
, nãoisinstance(A, object)
, não? Com o último, você está testando se a classeA
é umaobject
, enquanto a questão é se as instâncias deA
são umaobject
, certo?issubclass(HTMLParser, object)
, que retorna False.a maneira correta de fazer será a seguinte nas classes de estilo antigo que não herdam de 'objeto'
fonte
A
que armazena um estado.FWIW e, embora eu não seja um guru de Python, convivi com isso
Apenas recebi os resultados da análise, conforme necessário.
fonte