The following use of super()
raises a TypeError: why?
>>> from HTMLParser import HTMLParser
>>> class TextParser(HTMLParser):
... def __init__(self):
... super(TextParser, self).__init__()
... self.all_data = []
...
>>> TextParser()
(...)
TypeError: must be type, not classobj
There is a similar question on StackOverflow: Python super() raises TypeError, where the error is explained by the fact that the user class is not a new-style class. However, the class above is a new-style class, as it inherits from object
:
>>> isinstance(HTMLParser(), object)
True
What am I missing? How can I use super()
, here?
Using HTMLParser.__init__(self)
instead of super(TextParser, self).__init__()
would work, but I would like to understand the TypeError.
PS: Joachim pointed out that being a new-style-class instance is not equivalent to being an object
. I read the opposite many times, hence my confusion (example of new-style class instance test based on object
instance test: https://stackoverflow.com/revisions/2655651/3).
This question is related to
python
superclass
super
typeerror
FWIW and though I'm no Python guru I got by with this
>>> 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
(...)
Just got me the parse results back as needed.
You can also use class TextParser(HTMLParser, object):
. This makes TextParser
a new-style class, and super()
can be used.
If you look at the inheritance tree (in version 2.6), HTMLParser
inherits from SGMLParser
which inherits from ParserBase
which doesn't inherits from object
. I.e. HTMLParser is an old-style class.
About your checking with isinstance
, I did a quick test in ipython:
In [1]: class A: ...: pass ...: In [2]: isinstance(A, object) Out[2]: True
Even if a class is old-style class, it's still an instance of object
.
the correct way to do will be as following in the old-style classes which doesn't inherit from 'object'
class A:
def foo(self):
return "Hi there"
class B(A):
def foo(self, name):
return A.foo(self) + name
super() can be used only in the new-style classes, which means the root class needs to inherit from the 'object' class.
For example, the top class need to be like this:
class SomeClass(object):
def __init__(self):
....
not
class SomeClass():
def __init__(self):
....
So, the solution is that call the parent's init method directly, like this way:
class TextParser(HTMLParser):
def __init__(self):
HTMLParser.__init__(self)
self.all_data = []
The problem is that super
needs an object
as an ancestor:
>>> 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
On closer examination one finds:
>>> type(myclass)
classobj
But:
>>> class newstyle(object): pass
>>> type(newstyle)
type
So the solution to your problem would be to inherit from object as well as from HTMLParser. But make sure object comes last in the classes MRO:
>>> class myclass(oldstyle, object):
... def __init__(self): super(myclass, self).__init__()
>>> myclass().os
True
Source: Stackoverflow.com