Următoarele utilizarea de super()` ridică o TypeError: de ce?
>>> from HTMLParser import HTMLParser
>>> class TextParser(HTMLParser):
... def __init__(self):
... super(TextParser, self).__init__()
... self.all_data = []
...
>>> TextParser()
(...)
TypeError: must be type, not classobj
Există o întrebare similară pe StackOverflow: https://stackoverflow.com/questions/489269/python-super-raises-typeerror-why, în cazul în care eroarea este explicat prin faptul că utilizatorul de clasă nu este un nou stil de clasa. Cu toate acestea, clasa de mai sus este un stil nou de clasa, ca-l moștenește de la "obiect":
>>> isinstance(HTMLParser(), object)
True
Ce sunt eu lipsesc? Cum pot folosi super()`, aici?
Folosind HTMLParser.__init__(self) "în loc de" super(TextParser, auto).__init__()
ar lucra, dar aș dori să se înțeleagă TypeError.
PS: Joachim a subliniat că, fiind un stil nou-exemplu de clasă nu este echivalent cu a fi un "obiect". Am citit opus de mai multe ori, de aici confuzia mea (exemplu de stil nou exemplu de clasă test bazat pe "obiect" exemplu de test: https://stackoverflow.com/revisions/2655651/3).
Bine, l's de obicei " super()` nu poate fi utilizat cu un stil vechi de clasa".
Cu toate acestea, cel mai important este că testul corect pentru "este un stil nou exemplu (de ex.)?" este
>>> class OldStyle: pass
>>> instance = OldStyle()
>>> issubclass(instance.__class__, object)
False
și nu (ca în întrebare):
>>> isinstance(instance, object)
True
Pentru clase, corectă "este un stil nou de clasa" de testare este:
>>> issubclass(OldStyle, object) # OldStyle is not a new-style class
False
>>> issubclass(int, object) # int is a new-style class
True
La punct crucial este asta cu stil vechi clase, clasa a un exemplu și tip sunt distincte. Aici, OldStyle().__clasa__ "este" OldStyle
, care nu se moștenesc de la "obiect", în timp ce tip(OldStyle())
este "exemplu" de tip, care nu moșteni de la "obiect". Practic, un stil vechi de clasă creează doar obiecte de tip "exemplu" (întrucât un nou stil de clasă creează obiecte al căror tip este o clasa in sine). Acesta este probabil motivul exemplu OldStyle()
este un "obiect": sa tip()
moștenește de la "obiect" (faptul că clasa sa nu moșteni de la "obiect" nu se pune: stil vechi clase doar construi noi obiecte de tip "exemplu"). Parțială de referință: https://stackoverflow.com/a/9699961/42973.
PS: diferenta dintre un nou stil de clasă și un vechi stil poate fi, de asemenea, văzut cu:
>>> 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
(stil vechi clase sunt nu tipuri, astfel încât acestea nu pot fi tipul de cazuri).
super() pot fi utilizate numai în noul stil clase, ceea ce înseamnă clasa rădăcină trebuie să moștenesc de la 'obiect' clasa.
De exemplu, clasa de top trebuie să fie ca aceasta:
class SomeClass(object):
def __init__(self):
....
nu
class SomeClass():
def __init__(self):
....
Deci, soluția este apelul părintelui's init metoda direct, ca în acest fel:
class TextParser(HTMLParser):
def __init__(self):
HTMLParser.__init__(self)
self.all_data = []
Puteți folosi, de asemenea, clasa TextParser(HTMLParser, obiect):. Acest lucru face
TextParsero *stil nou* clasă, și super()
poate fi folosit.
Problema este că "super" are nevoie de un "obiect" ca un strămoș:
>>> 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
La o examinare mai atentă se constată:
>>> type(myclass)
classobj
Dar:
>>> class newstyle(object): pass
>>> type(newstyle)
type
Deci solutia la problema ta ar fi să moștenească de la obiect la fel de bine ca la HTMLParser. Dar asigurați-vă că obiect vine trecută în clase MRO:
>>> class myclass(oldstyle, object):
... def __init__(self): super(myclass, self).__init__()
>>> myclass().os
True
Dacă te uiți la moștenire copac (în versiunea 2.6), HTMLParser
moștenește de la SGMLParser
care moștenește de la ParserBase
care doesn't moștenește de la "obiect". I. e. HTMLParser este un vechi stil de clasa.
Despre verificarea cu isinstance`, am facut un test rapid în ipython:
În [1]: clasa a: ...: pass ...:În [2]: isinstance(Un obiect) Out[2]: Adevărat
Chiar dacă o clasă este de stil vechi din clasa, l's încă un exemplu de "obiect".
modul corect de a face va fi după cum urmează în stil vechi clase care nu't moșteni de la 'obiect'
class A:
def foo(self):
return "Hi there"
class B(A):
def foo(self, name):
return A.foo(self) + name
FWIW și, deși am'm nu Python guru-am luat cu asta
>>> class TextParser(HTMLParser):
... def handle_starttag(self, tag, attrs):
... if tag == "b":
... self.all_data.append("bold")
... else:
... self.all_data.append("other")
...
...
>>> p = TextParser()
>>> p.all_data = []
>>> p.feed(text)
>>> print p.all_data
(...)
Mi-a luat analiza rezultatele înapoi după cum este necesar.