Następujące użycie super()
podnosi typ błędu: dlaczego?
>>> from HTMLParser import HTMLParser
>>> class TextParser(HTMLParser):
... def __init__(self):
... super(TextParser, self).__init__()
... self.all_data = []
...
>>> TextParser()
(...)
TypeError: must be type, not classobj
Podobne pytanie dotyczy StackOverflow: Python super () podnosi TypeError , gdzie błąd jest wyjaśniony przez fakt, że klasa użytkownika nie jest klasą nowego stylu. Jednak powyższa klasa jest klasą w nowym stylu, ponieważ dziedziczy po object
:
>>> isinstance(HTMLParser(), object)
True
czego mi brakuje? Jak mogę użyć super()
tutaj?
Używanie HTMLParser.__init__(self)
zamiast super(TextParser, self).__init__()
byłoby działało, ale chciałbym zrozumieć błąd TypeError.
PS: Joachim wskazał, że bycie instancją klasy nowego stylu nie jest równoznaczne z byciem an object
. Wiele razy czytam przeciwieństwo, stąd moje zamieszanie (przykład testu instancji klasy w nowym stylu na podstawie object
testu instancji: https://stackoverflow.com/revisions/2655651/3 ).
źródło
super.__doc__
nie wspomina o starym i nowym stylu!super()
działa tylko w przypadku klas (i obiektów) w nowym stylu, jest wspomniany w dokumencie HTML ( docs.python.org/library/functions.html#super ).Odpowiedzi:
W porządku, to zwykłe „
super()
nie można używać z klasą w starym stylu”.Ważną kwestią jest jednak to, czy poprawny test „czy jest to instancja w nowym stylu (tj. Obiekt)?” jest
a nie (jak w pytaniu):
W przypadku klas poprawny test „czy to klasa nowego stylu” to:
Kluczowym punktem jest to, że z zajęć w starym stylu, klasy z instancji i jego rodzaj są różne. Tutaj
OldStyle().__class__
jestOldStyle
, co nie dziedzicząobject
, podczas gdytype(OldStyle())
jest toinstance
typ, który ma dziedziczyćobject
. Zasadniczo klasa w starym stylu po prostu tworzy obiekty typuinstance
(podczas gdy klasa w nowym stylu tworzy obiekty, których typem jest sama klasa). Prawdopodobnie dlatego instancjaOldStyle()
jest następującaobject
:type()
dziedziczy poobject
( nie liczy się to, że jej klasa nie dziedziczyobject
: klasy w starym stylu jedynie konstruują nowe obiekty typuinstance
). Częściowe odniesienie:https://stackoverflow.com/a/9699961/42973 .PS: Różnicę między klasą w nowym stylu a klasą w starym stylu można również zobaczyć w:
(klasy w starym stylu nie są typami, więc nie mogą być typem swoich instancji).
źródło
(Oldstyle().__class__ is Oldstyle)
jestTrue
OldStyle().__class__
to, aby pokazać, jak sprawdzić, czy obiekt (OldStyle()
) pochodzi z klasy w starym stylu. Mając na uwadze wyłącznie zajęcia w nowym stylu, można pokusić się o wykonanie testuisinstance(OldStyle(), object)
.object
, więc przykręcenie cię przez pełnomocnika.super () może być używane tylko w klasach w nowym stylu, co oznacza, że klasa główna musi dziedziczyć po klasie „object”.
Na przykład najwyższa klasa musi wyglądać tak:
nie
Tak więc rozwiązaniem jest bezpośrednie wywołanie metody init rodzica , w następujący sposób:
źródło
self
parametru wHTMLParser.__init__()
wywołaniu.Możesz także użyć
class TextParser(HTMLParser, object):
. To sprawia, żeTextParser
do nowego stylu klasy isuper()
mogą być użyte.źródło
Problem w tym, że
super
potrzebujeobject
przodka:Przy bliższym zbadaniu stwierdza się:
Ale:
Rozwiązaniem Twojego problemu byłoby dziedziczenie po obiektach, a także po HTMLParser. Ale upewnij się, że obiekt jest na końcu klasy MRO:
źródło
type(myclass)
, ważne jest to, czymyclass
dziedziczymy po obiekcie (tj. Czyisinstance(myclass, object)
jest to prawda - jest to fałsz).Jeśli spojrzysz na drzewo dziedziczenia (w wersji 2.6),
HTMLParser
dziedziczy, zSGMLParser
którego dziedziczy, zParserBase
którego nie dziedziczyobject
. Tj. HTMLParser jest klasą w starym stylu.Jeśli chodzi o sprawdzanie
isinstance
, zrobiłem szybki test w ipython:Nawet jeśli klasa jest klasą w starym stylu, nadal jest instancją klasy
object
.źródło
isinstance(A(), object)
nieisinstance(A, object)
, nie? Z tym ostatnim, testujesz, czy klasaA
jestobject
, natomiast pytanie, czy przypadki zA
sąobject
, prawda?issubclass(HTMLParser, object)
, że najlepszym testem jest Fałsz.poprawny sposób postępowania będzie taki, jak w klasach w starym stylu, który nie dziedziczy po „obiekcie”
źródło
A
która przechowuje stan.FWIW i chociaż nie jestem guru Pythona, poradziłem sobie z tym
Właśnie dostałem wyniki analizy w razie potrzeby.
źródło