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,该错误由用户类不是新型类的事实。但是,上面的类是一种新型类,因为它继承自
object
:>>> isinstance(HTMLParser(), object)
True
我缺少什么?
使用
super()
代替HTMLParser.__init__(self)
是可以的,但我想了解TypeError。PS:Joachim指出这是一种新方法-style-class实例并不等同于
super(TextParser, self).__init__()
。我读了很多相反的书,因此感到困惑(基于object
实例测试的新型类实例测试的示例:https://stackoverflow.com/revisions/2655651/3)。#1 楼
好吧,这是通常的“super()
不能与旧式类一起使用”。但是,重要的一点是正确的测试是“这是新式实例(即对象)吗? ”是
>>> class OldStyle: pass
>>> instance = OldStyle()
>>> issubclass(instance.__class__, object)
False
,而不是(如出现问题):
>>> isinstance(instance, object)
True
对于类,正确的“这是新样式类吗?测试是:
>>> issubclass(OldStyle, object) # OldStyle is not a new-style class
False
>>> issubclass(int, object) # int is a new-style class
True
关键点在于,对于旧样式类,实例的类及其类型是不同的。在这里,
OldStyle().__class__
是OldStyle
,它不继承自object
,而type(OldStyle())
是instance
类型,它确实继承自object
。基本上,旧类仅创建类型为instance
的对象(而新类将创建其类型为该类本身的对象)。这可能就是为什么实例OldStyle()
是object
的原因:其type()
继承自object
(其类不继承自object
的事实不计算在内:旧式类仅构造了instance
类型的新对象)。部分参考: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
(旧类不是类型,因此它们不能是其实例的类型)。
评论
这就是我们现在拥有Python 3的原因之一。
–史蒂文·鲁姆巴尔斯基(Steven Rumbalski)
2012年3月15日15:09
顺便说一句:(Oldstyle().__ class__是Oldstyle)是True
– Tino
2012年10月28日16:13
@Tino:的确如此,但是OldStyle().__ class__的要点是显示如何测试对象(OldStyle())是否来自旧类。考虑到只有新式类,可能会倾向于使用isinstance(OldStyle(),object)进行测试。
– Eric O Lebigot
13年3月3日,11:49
荒谬的是,2.7.x中仍然有多少python标准库没有从对象继承,因此代理会给您带来麻烦。
–尼克·巴斯汀(Nick Bastin)
13-10-12在4:23
@NickBastin-这不是巧合。所有这些都是为了将所有人推入Python3。在这里,“一切都很好”。但是-告急者-只是诱饵和开关。
– Tomasz Gandor
14-10-20在12:57
#2 楼
super()只能在新型类中使用,这意味着根类需要从'object'类继承。例如,顶层类需要这样:
class SomeClass(object):
def __init__(self):
....
not
class SomeClass():
def __init__(self):
....
因此,解决方案是直接调用父级的init方法,如下所示:
class TextParser(HTMLParser):
def __init__(self):
HTMLParser.__init__(self)
self.all_data = []
评论
对我来说,我必须这样做:HTMLParser .__ init __(self)我很好奇您的上一个示例是否有效?
–聊天
2012年11月27日在1:31
@EOL是什么意思? jeffp刚刚指出,由于HTMLParser .__ init __()调用中缺少自我参数,此答案中给出的代码是错误的。
–彼得·多布罗格斯特(Piotr Dobrogost)
13年5月24日15:00
@PiotrDobrogost:对不起,我的评论是关于LittleQ的答案,而不是关于jeffp的(好)观点。
– Eric O Lebigot
13年5月25日在9:14
@jeffp对不起,这是一个错字,我只是在SO上打出来,但没有测试,我的错。感谢您的纠正
–苏琳(Colin Su)
2013年9月25日上午8:18
支持适用于现有代码的修复程序,例如python2.6中的logging.Formatter
–大卫·雷诺兹(David Reynolds)
2014年4月25日在10:23
#3 楼
您也可以使用class TextParser(HTMLParser, object):
。这使TextParser
成为新的类,并且可以使用super()
。评论
我的反对,因为添加对象的继承是一个好主意。 (也就是说,此答案并未解决理解该问题的TypeError的问题。)
– Eric O Lebigot
13年5月12日在1:10
#4 楼
问题在于,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
所以解决问题的方法是从对象以及HTMLParser继承。
但是请确保对象在MRO类中排在最后:
>>> class myclass(oldstyle, object):
... def __init__(self): super(myclass, self).__init__()
>>> myclass().os
True
评论
有效点,但是它们已经在先前的答案中。另外,重要的是,myclass是否从对象继承(即isinstance(myclass,object)是否为true —它为false),而不是检查type(myclass)。
– Eric O Lebigot
15-10-18在15:08
#5 楼
如果查看继承树(在2.6版中),则HTMLParser
继承自SGMLParser
,后者继承自ParserBase
,而不继承自object
。即HTMLParser是一个老式的类。关于您使用
isinstance
进行检查,我在ipython中进行了快速测试:In [1]: class A: ...: pass ...: In [2]: isinstance(A, object) Out[2]: True
class是老式的类,它仍然是
object
的实例。评论
我认为正确的测试应该是isinstance(A(),object),而不是isinstance(A,object),不是吗?使用后者,您正在测试类A是否是对象,而问题是A的实例是否是对象,对吗?
– Eric O Lebigot
2012年3月14日9:40
PS:最好的测试似乎是issubclass(HTMLParser,object),它返回False。
– Eric O Lebigot
2012年3月14日在9:51
#6 楼
正确的方法是在不继承自'object'的旧类中进行以下操作class A:
def foo(self):
return "Hi there"
class B(A):
def foo(self, name):
return A.foo(self) + name
评论
在问题中,已经提到了这种方法:问题是要理解为什么会产生错误消息,而不是使其消失(特别是以此方式)。
– Eric O Lebigot
2014年2月25日在2:23
此外,在我们要调用存储状态的类A实例的情况下,此解决方案将不起作用。
– Tashuhka
2015年6月9日15:37
评论
感谢您的提问和回答。我想知道为什么2.7的super .__ doc__没有提及新旧样式!谢谢。 :)文档字符串通常比完整的HTML版本的文档包含更少的信息。 HTML文档(docs.python.org/library/functions.html#super)中提到了super()仅适用于新型类(和对象)的事实。
python super()的可能重复项引发TypeError!为什么?
这不是重复的内容(请参阅更新的问题和接受的答案)。