super () вызывает "TypeError: должен быть тип, а не classobj" для класса нового стиля
следующее использование super()
поднимает TypeError: почему?
>>> from HTMLParser import HTMLParser
>>> class TextParser(HTMLParser):
... def __init__(self):
... super(TextParser, self).__init__()
... self.all_data = []
...
>>> TextParser()
(...)
TypeError: must be type, not classobj
есть аналогичный вопрос на StackOverflow:Python super () вызывает TypeError, где ошибка объясняется тем, что пользовательский класс не является классом нового стиля. Однако класс выше является классом нового стиля, поскольку он наследует от object
:
>>> isinstance(HTMLParser(), object)
True
что я упустил? Как я могу использовать super()
здесь?
используя HTMLParser.__init__(self)
вместо super(TextParser, self).__init__()
будет работать, но я хотел бы понять ошибку TypeError.
PS: Иоахим указал, что быть экземпляром класса нового стиля не эквивалентно быть object
. Я читал противоположное много раз, поэтому моя путаница (пример теста экземпляра класса нового стиля на основе object
тест экземпляра:https://stackoverflow.com/revisions/2655651/3).
6 ответов:
ладно, все как обычно"
super()
не может использоваться с классом старого стиля".однако, важным моментом является то, что корректный тест ибо " это новый стиль экземпляр (т. е. объект)?"это
>>> class OldStyle: pass >>> instance = OldStyle() >>> issubclass(instance.__class__, object) False
, а не (как в вопросе):
>>> isinstance(instance, object) True
на классы, правильный тест" это класс нового стиля":
>>> issubclass(OldStyle, object) # OldStyle is not a new-style class False >>> issubclass(int, object) # int is a new-style class True
The ключевой момент заключается в том, что с старые классы, в класс экземпляра и его тип различны. Вот,
OldStyle().__class__
иOldStyle
, который не наследует отobject
, аtype(OldStyle())
- этоinstance
тип, который тут наследовать отobject
. В принципе, класс старого стиля просто создает объекты типаinstance
(в то время как класс нового стиля создает объекты, типом которых является сам класс). Вероятно, поэтому экземплярOldStyle()
этоobject
: егоtype()
наследует отobject
(тот факт, что его класс не наследовать отobject
не считается: классы старого стиля просто создают новые объекты типаinstance
). Частичная ссылка: https://stackoverflow.com/a/9699961/42973.PS: разницу между классом нового стиля и классом старого стиля также можно увидеть с помощью:
>>> type(OldStyle) # OldStyle creates objects but is not itself a type classobj >>> isinstance(OldStyle, type) False >>> type(int) # A new-style class is a type type
(старого стиля классы не типы, поэтому они не могут быть типа их экземпляры).
super () может использоваться только в классах нового стиля, что означает, что корневой класс должен наследовать от класса 'object'.
например, высший класс должен быть таким:
class SomeClass(object): def __init__(self): ....
не
class SomeClass(): def __init__(self): ....
Итак, решение заключается в том, что вызов родителей init метод напрямую, вот так:
class TextParser(HTMLParser): def __init__(self): HTMLParser.__init__(self) self.all_data = []
вы также можете использовать
class TextParser(HTMLParser, object):
. Это делаетTextParser
a новый стиль класс, аsuper()
можно использовать.
проблема в том, что
super
нуженobject
как предок:>>> class oldstyle: ... def __init__(self): self.os = True >>> class myclass(oldstyle): ... def __init__(self): super(myclass, self).__init__() >>> myclass() TypeError: must be type, not classobj
при ближайшем рассмотрении обнаруживаешь:
>>> type(myclass) classobj
но:
>>> class newstyle(object): pass >>> type(newstyle) type
таким образом, решение вашей проблемы будет наследовать от объекта, а также от HTMLParser. Но убедитесь, что объект приходит последним в классах MRO:
>>> class myclass(oldstyle, object): ... def __init__(self): super(myclass, self).__init__() >>> myclass().os True
если вы посмотрите на дерево наследования (в версии 2.6),
HTMLParser
наследует отSGMLParser
, который наследует отParserBase
, который не наследует отobject
. То есть HTMLParser-это класс старого стиля.о проверке с
isinstance
, Я сделал быстрый тест в IPython:In [1]: class A: ...: pass ...: In [2]: isinstance(A, object) Out[2]: Trueдаже если класс является классом старого стиля, это все равно экземпляр
object
.