The following use of super()
raises a TypeError: why?
super()的以下用法引出了一个类型错误:为什么?
>>> 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 *: 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
:
在*上有一个类似的问题:Python super()引发了TypeError,其中的错误可以通过用户类不是新样式类这一事实来解释。但是,上面的类是一个新样式的类,因为它继承自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.
使用htmlparres .__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
. I read the opposite many times, hence my confusion (example of new-style class instance test based on object
instance test: https://*.com/revisions/2655651/3).
Joachim指出,作为一个新的样式类实例并不等同于对象。我多次读到相反的内容,因此我感到困惑(基于对象实例测试的新样式类实例测试示例:https://*.com/revisions/2655651/1/3)。
6 个解决方案
#1
234
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 (i.e. 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
. Basically, an old-style class just creates objects of type instance
(whereas a new-style class creates objects whose type is the class itself). 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
). Partial reference: https://*.com/a/9699961/42973.
关键的一点是,对于旧式类,实例的类及其类型是不同的。在这里,OldStyle()。__class__是OldStyle,它不从对象继承,而type(OldStyle())是实例类型,它从对象继承。基本上,旧式类只创建类型实例的对象(而新式类创建的对象类型是类本身)。这可能就是为什么实例OldStyle()是一个对象:它的type()继承自object(它的类没有从object继承的事实不算数:旧式类仅仅构造类型instance的新对象)。部分参考:https://*.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).
(旧式类不是类型,所以它们不能是实例的类型)。
#2
186
super() can be used only in the new-style classes, which means the root class needs to inherit from the 'object' class.
super()只能在新样式的类中使用,这意味着根类需要从“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 = []
#3
25
You can also use class TextParser(HTMLParser, object):
. This makes TextParser
a new-style class, and super()
can be used.
您还可以使用类TextParser(HTMLParser, object):。这使得TextParser成为一种新型的类,并且可以使用super()。
#4
17
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.
如果您查看继承树(在2.6版本中),HTMLParser从SGMLParser继承而来,SGMLParser从ParserBase继承而来,ParserBase没有从object继承。例如,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
.
即使类是旧式类,它仍然是对象的实例。
#5
17
The problem is that super
needs an object
as a ancestor:
问题是super需要一个对象作为祖先:
>>> 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:
因此,您的问题的解决方案是继承对象和HTMLParser。但要确保对象在MRO类中排在最后:
>>> class myclass(oldstyle, object):
... def __init__(self): super(myclass, self).__init__()
>>> myclass().os
True
#6
4
the correct way to do will be as following in the old-style classes which doesn't inherit from 'object'
正确的做法是在老式的类中这样做,这些类不从'object'继承
class A:
def foo(self):
return "Hi there"
class B(A):
def foo(self, name):
return A.foo(self) + name
#1
234
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 (i.e. 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
. Basically, an old-style class just creates objects of type instance
(whereas a new-style class creates objects whose type is the class itself). 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
). Partial reference: https://*.com/a/9699961/42973.
关键的一点是,对于旧式类,实例的类及其类型是不同的。在这里,OldStyle()。__class__是OldStyle,它不从对象继承,而type(OldStyle())是实例类型,它从对象继承。基本上,旧式类只创建类型实例的对象(而新式类创建的对象类型是类本身)。这可能就是为什么实例OldStyle()是一个对象:它的type()继承自object(它的类没有从object继承的事实不算数:旧式类仅仅构造类型instance的新对象)。部分参考:https://*.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).
(旧式类不是类型,所以它们不能是实例的类型)。
#2
186
super() can be used only in the new-style classes, which means the root class needs to inherit from the 'object' class.
super()只能在新样式的类中使用,这意味着根类需要从“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 = []
#3
25
You can also use class TextParser(HTMLParser, object):
. This makes TextParser
a new-style class, and super()
can be used.
您还可以使用类TextParser(HTMLParser, object):。这使得TextParser成为一种新型的类,并且可以使用super()。
#4
17
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.
如果您查看继承树(在2.6版本中),HTMLParser从SGMLParser继承而来,SGMLParser从ParserBase继承而来,ParserBase没有从object继承。例如,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
.
即使类是旧式类,它仍然是对象的实例。
#5
17
The problem is that super
needs an object
as a ancestor:
问题是super需要一个对象作为祖先:
>>> 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:
因此,您的问题的解决方案是继承对象和HTMLParser。但要确保对象在MRO类中排在最后:
>>> class myclass(oldstyle, object):
... def __init__(self): super(myclass, self).__init__()
>>> myclass().os
True
#6
4
the correct way to do will be as following in the old-style classes which doesn't inherit from 'object'
正确的做法是在老式的类中这样做,这些类不从'object'继承
class A:
def foo(self):
return "Hi there"
class B(A):
def foo(self, name):
return A.foo(self) + name