super()为新样式类提出了“类型错误:必须是类型,而不是classobj”

时间:2021-09-22 16:56:55

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