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
,它不从object
inheritance,而type(OldStyle())
是从object
inheritance的instance
types。 基本上,一个旧式的类只是创buildtypesinstance
对象(而新式类创build的对象的types是类本身)。 这可能是为什么实例OldStyle()
是一个object
:它的type()
inheritance自object
(它的类不能从object
inheritance的事实不算:旧式类只是构造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自不从object
inheritance的ParserBase
SGMLParser
inheritance。 即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