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