super()失败,并显示错误:当父级未从对象继承时,TypeError“参数1必须为类型,而不是classobj”


196

我收到一些我不知道的错误。任何线索我的示例代码有什么问题吗?

class B:
    def meth(self, arg):
        print arg

class C(B):
    def meth(self, arg):
        super(C, self).meth(arg)

print C().meth(1)

我从“ super”内置方法的帮助下获得了示例测试代码。

这是错误:

Traceback (most recent call last):
  File "./test.py", line 10, in ?
    print C().meth(1)
  File "./test.py", line 8, in meth
    super(C, self).meth(arg)
TypeError: super() argument 1 must be type, not classobj

仅供参考,这是python本身的帮助(超级):

Help on class super in module __builtin__:

class super(object)
 |  super(type) -> unbound super object
 |  super(type, obj) -> bound super object; requires isinstance(obj, type)
 |  super(type, type2) -> bound super object; requires issubclass(type2, type)
 |  Typical use to call a cooperative superclass method:
 |  class C(B):
 |      def meth(self, arg):
 |          super(C, self).meth(arg)
 |


3
方法?那是编程术语,还是……知道吗?请澄清。
Cplusplusplus 2015年

3
@Cplusplusplus:可能代表方法;-)
ShadowFlame 2015年

Answers:


333

您的问题是类B没有声明为“新式”类。像这样更改它:

class B(object):

它会工作。

super()并且所有子类/超类的内容仅适用于新型类。我建议您养成始终(object)在任何类定义上键入它的习惯,以确保它是一种新型的类。

旧式类(也称为“经典”类)始终为type classobj;新样式类的类型为type。这就是为什么您看到错误消息的原因:

TypeError: super() argument 1 must be type, not classobj

试试看自己:

class OldStyle:
    pass

class NewStyle(object):
    pass

print type(OldStyle)  # prints: <type 'classobj'>

print type(NewStyle) # prints <type 'type'>

请注意,在Python 3.x中,所有类都是新样式。您仍然可以使用旧样式类中的语法,但是会获得新样式类。因此,在Python 3.x中,您将不会遇到此问题。


有趣的是,我发现在运行bottle.py(bottlepy.org)时遇到了这个确切的问题,它在Py27而非Py33上运行时抛出类似的错误(TypeError:必须为type,不是classobj)。
bootload

在Python 3.x中,不再有“旧式”类。使用“旧样式”声明的代码仍声明“新样式”类,因此在Python 3.x中不会发生此错误。
steveha 2014年

1
如果您无法编辑B类,则必须编辑A类以免尝试使用super()。必须使A类与“旧式”类一起使用,并且做到这一点的最佳方法可能是使A类本身成为“旧式”类。当然,我建议您只升级整个程序使其在Python 3.x中运行,这样无论您做什么,所有类都是新样式。如果该选项可用,那是最好的选择。
steveha '18

我有同样的问题,但是我的基类声明为class B(object):。由于@mock.patch('module.B', autospec=B)在测试用例之前使用,导致出现此错误。有关如何解决此问题的任何想法?
MikeyE

154

另外,如果您不能更改类B,则可以使用多重继承来修复错误。

class B:
    def meth(self, arg):
        print arg

class C(B, object):
    def meth(self, arg):
        super(C, self).meth(arg)

print C().meth(1)

16
我不禁发表评论,这个评论应该被接受为“标准”答案。
workplaylifecycle 2014年

9
对于那些坚持使用Python 2.6的未来Google员工:这可能是您想要的答案!当您不能更改基类时(例如,您正在对标准库类进行子类化),对您自己的类的此更改将修复super()。
coredumperror 2015年

它对我来说很好用,您能解释一下它是如何工作的吗?
Subro

@subro,这使您的类成为“新式”类(其中类对象是类型type),同时仍然继承“旧式”类(其类对象是类型classobj)。super()适用于新样式类,但不适用于旧样式类。
MarSoft

完美的答案!
汤姆(Tom)

18

如果python版本是3.X,就可以了。

我认为您的python版本是2.X,在添加此代码时,超级将可用

__metaclass__ = type

所以代码是

__metaclass__ = type
class B:
    def meth(self, arg):
        print arg
class C(B):
    def meth(self, arg):
        super(C, self).meth(arg)
print C().meth(1)

4

当我使用python 2.7时,也会遇到发布的问题。它在python 3.4下工作得很好

为了使其在python 2.7中工作,我__metaclass__ = type在程序顶部添加了该属性,并且该属性可以正常工作。

__metaclass__ :简化了从旧样式类到新样式类的过渡。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.