[英]super() raises “TypeError: must be type, not classobj” for new-style class
The following use of super()
raises a TypeError: why? 以下使用
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
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. StackOverflow上有一个类似的问题: Python super()引发TypeError ,其中错误的解释是用户类不是新式类。 However, the class above is a new-style class, as it inherits from
object
: 但是,上面的类是一个新式类,因为它继承自
object
:
>>> isinstance(HTMLParser(), object)
True
What am I missing? 我错过了什么? How can I use
super()
, here? 我怎么能在这里使用
super()
?
Using HTMLParser.__init__(self)
instead of super(TextParser, self).__init__()
would work, but I would like to understand the TypeError. 使用
HTMLParser.__init__(self)
而不是super(TextParser, self).__init__()
可以工作,但我想了解TypeError。
PS: Joachim pointed out that being a new-style-class instance is not equivalent to being an object
. PS:Joachim指出,作为一个新式的实例并不等同于成为一个
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 ). 我多次反复阅读,因此我的困惑(基于
object
实例测试的新式类实例测试示例: https : //stackoverflow.com/revisions/2655651/3 )。
Alright, it's the usual " super()
cannot be used with an old-style class". 好吧,这是通常的“
super()
不能用于旧式的”。
However, the important point is that the correct test for "is this a new-style instance (ie object)?" 然而,重要的一点是正确的测试 “这是一个新风格的实例 (即对象)?” is
是
>>> class OldStyle: pass
>>> instance = OldStyle()
>>> issubclass(instance.__class__, object)
False
and not (as in the question): 而不是(如在问题中):
>>> isinstance(instance, object)
True
For classes , the correct "is this a new-style class" test is: 对于类 ,正确的“这是一个新式的类”测试是:
>>> issubclass(OldStyle, object) # OldStyle is not a new-style class
False
>>> issubclass(int, object) # int is a new-style class
True
The crucial point is that with old-style classes, the class of an instance and its type are distinct. 关键点在于,对于旧式类,实例的类及其类型是不同的。 Here,
OldStyle().__class__
is OldStyle
, which does not inherit from object
, while type(OldStyle())
is the instance
type, which does inherit from object
. 这里,
OldStyle().__class__
是OldStyle
,其不从继承object
,而type(OldStyle())
是instance
类型, 它从继承object
。 Basically, an old-style class just creates objects of type instance
(whereas a new-style class creates objects whose type is the class itself). 基本上,旧式类只创建类型
instance
对象(而新式类创建类型为类本身的对象)。 This is probably why the instance OldStyle()
is an object
: its type()
inherits from object
(the fact that its class does not inherit from object
does not count: old-style classes merely construct new objects of type instance
). 这大概就是为什么实例
OldStyle()
是一个object
:它的type()
从继承object
(事实上,它的类没有从继承object
:老式类只是构建类型的新对象不计算instance
)。 Partial reference: https://stackoverflow.com/a/9699961/42973 . 部分参考: https : //stackoverflow.com/a/9699961/42973 。
PS: The difference between a new-style class and an old-style one can also be seen with: 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
(old-style classes are not types, so they cannot be the type of their instances). (旧式类不是类型,因此它们不能是它们实例的类型)。
super() can be used only in the new-style classes, which means the root class needs to inherit from the 'object' class. super()只能在new-style类中使用,这意味着root类需要从'object'类继承。
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: 所以,解决方案是直接调用父的init方法,就像这样:
class TextParser(HTMLParser):
def __init__(self):
HTMLParser.__init__(self)
self.all_data = []
You can also use class TextParser(HTMLParser, object):
. 您还可以使用
class TextParser(HTMLParser, object):
This makes TextParser
a new-style class, and super()
can be used. 这使得
TextParser
成为一种新式的类,并且可以使用super()
。
The problem is that super
needs an object
as an ancestor: 问题是
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
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. 因此,您的问题的解决方案是从对象以及HTMLParser继承。 But make sure object comes last in the classes MRO:
但要确保对象在MRO类中排在最后:
>>> class myclass(oldstyle, object):
... def __init__(self): super(myclass, self).__init__()
>>> myclass().os
True
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
. 如果查看继承树(在2.6版本中),
HTMLParser
继承自从ParserBase
继承的SGMLParser
,它不从object
继承。 Ie HTMLParser is an old-style class. 即HTMLParser是一个旧式的类。
About your checking with isinstance
, I did a quick test in ipython: 关于你的
isinstance
,我在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
. 即使一个类是旧式类,它仍然是一个
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
FWIW and though I'm no Python guru I got by with this FWIW虽然我不是Python大师,但我还是接受了这个
>>> 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. 刚刚根据需要解析了解析结果。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.