super() raises “TypeError: must be type, not classobj” for new-style class
下面使用
1 2 3 4 5 6 7 8 9 | >>> 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,错误的解释是用户类不是一个新样式的类。但是,上面的类是一个新的样式类,因为它继承了
1 2 | >>> isinstance(HTMLParser(), object) True |
我错过了什么?这里我怎么用
使用
ps:joachim指出,作为一个新的样式类实例并不等同于一个
好吧,这是通常的"
但是,重要的一点是正确测试"这是一个新的样式的实例(即对象)"?是
1 2 3 4 | >>> class OldStyle: pass >>> instance = OldStyle() >>> issubclass(instance.__class__, object) False |
而不是(如问题所述):
1 2 | >>> isinstance(instance, object) True |
对于类,正确的"这是新样式类吗"测试是:
1 2 3 4 | >>> issubclass(OldStyle, object) # OldStyle is not a new-style class False >>> issubclass(int, object) # int is a new-style class True |
关键点是,对于旧样式类,实例的类及其类型是不同的。此处,
附言:一个新风格的班级和一个旧风格的班级之间的区别也可以通过以下方式看到:
1 2 3 4 5 6 | >>> 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 |
(旧样式类不是类型,因此不能是其实例的类型)。
super()只能在新样式的类中使用,这意味着根类需要从"object"类继承。
例如,顶级需要如下所示:
1 2 3 | class SomeClass(object): def __init__(self): .... |
不
1 2 3 | class SomeClass(): def __init__(self): .... |
因此,解决方案是直接调用父级的init方法,如下所示:
1 2 3 4 | class TextParser(HTMLParser): def __init__(self): HTMLParser.__init__(self) self.all_data = [] |
您也可以使用
问题是,
1 2 3 4 5 6 7 8 | >>> 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 |
仔细研究后,我们发现:
1 2 | >>> type(myclass) classobj |
但是:
1 2 3 4 | >>> class newstyle(object): pass >>> type(newstyle) type |
因此,解决问题的方法是从对象继承,也从HTMLParser继承。但是确保对象在类mro中排在最后:
1 2 3 4 5 | >>> class myclass(oldstyle, object): ... def __init__(self): super(myclass, self).__init__() >>> myclass().os True |
如果您查看继承树(在版本2.6中),那么
关于你和
1 2 3 4 5 6 | In [1]: class A: ...: pass ...: In [2]: isinstance(A, object) Out[2]: True |
即使一个类是老式类,它仍然是
正确的方法是在不从"object"继承的旧样式类中执行以下操作
1 2 3 4 5 6 7 | class A: def foo(self): return"Hi there" class B(A): def foo(self, name): return A.foo(self) + name |
尽管我不是Python大师,但我还是挺过来了。
1 2 3 4 5 6 7 8 9 10 11 12 13 | >>> class TextParser(HTMLParser): ... def handle_starttag(self, tag, attrs): ... if tag =="b": ... self.all_data.append("bold") ... else: ... self.all_data.append("other") ... ... >>> p = TextParser() >>> p.all_data = [] >>> p.feed(text) >>> print p.all_data (...) |
根据需要把分析结果给我。