super()引发新类风格的“TypeError:必须是types,而不是classobj”

以下使用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 

在StackOverflow中有一个类似的问题: Python super()引发了TypeError ,其中的错误是由用户类不是新风格的类来解释的。 然而,上面的类是一个新的类,因为它inheritance了object

 >>> isinstance(HTMLParser(), object) True 

我错过了什么? 我如何使用super() ,在这里?

使用HTMLParser.__init__(self)而不是super(TextParser, self).__init__()会工作,但我想了解TypeError。

PS:Joachim指出,作为一个新式的实例并不等同于一个object 。 我读了相反的多次,因此我的困惑(基于object实例testing的新式类实例testing的示例: https : //stackoverflow.com/revisions/2655651/3 )。

好吧,这是平常的“ super()不能用于旧式课堂”。

然而,重要的一点是,对于“这是一种新型实例 (即对象)” 的正确testing呢? 是

 >>> class OldStyle: pass >>> instance = OldStyle() >>> issubclass(instance.__class__, object) False 

而不是(如在问题中):

 >>> isinstance(instance, object) True 

对于class级来说 ,正确的“这是一种新式的class级”考试是:

 >>> issubclass(OldStyle, object) # OldStyle is not a new-style class False >>> issubclass(int, object) # int is a new-style class True 

关键的一点是,对于旧式类,实例的types是不同的。 在这里, OldStyle().__class__OldStyle ,它不从objectinheritance,而type(OldStyle())是从objectinheritance的instancetypes。 基本上,一个旧式的类只是创buildtypesinstance对象(而新式类创build的对象的types是类本身)。 这可能是为什么实例OldStyle()是一个object :它的type()inheritance自object (它的类不能objectinheritance的事实不算:旧式类只是构造typesinstance新对象)。 部分参考: https : //stackoverflow.com/a/9699961/42973 。

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 

(旧式类不是types,所以它们不能是它们实例的types)。

super()只能用于新风格的类,这意味着根类需要从“对象”类inheritance。

例如,顶级的类需要像这样:

 class SomeClass(object): def __init__(self): .... 

 class SomeClass(): def __init__(self): .... 

所以,解决方法是直接调用父类的init方法,就像这样:

 class TextParser(HTMLParser): def __init__(self): HTMLParser.__init__(self) self.all_data = [] 

你也可以使用class TextParser(HTMLParser, object): 这使TextParser成为一种新型的类,并且可以使用super()

如果您查看inheritance树(版本2.6), HTMLParser从inheritance自objectinheritance的ParserBase SGMLParserinheritance。 即HTMLParser是一个旧式的类。

关于您使用isinstance ,我在ipython中做了一个快速testing:

在[1]中:A类:
    ...:通过
    ...: 

在[2]中:isinstance(A,object)
出[2]:是的

即使一个类是旧式类,它仍然是一个object的实例。

问题是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 

仔细检查后发现:

 >>> type(myclass) classobj 

但:

 >>> class newstyle(object): pass >>> type(newstyle) type 

所以你的问题的解决scheme将是从HTMLParserinheritance对象。 但要确保对象在类MRO中最后:

 >>> class myclass(oldstyle, object): ... def __init__(self): super(myclass, self).__init__() >>> myclass().os True 

在不能从“对象”inheritance的旧式类中,正确的做法如下:

 class A: def foo(self): return "Hi there" class B(A): def foo(self, name): return A.foo(self) + name