Python super()引发TypeError


109

在Python 2.5中,以下代码引发TypeError

>>> class X:
      def a(self):
        print "a"

>>> class Y(X):
      def a(self):
        super(Y,self).a()
        print "b"

>>> c = Y()
>>> c.a()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 3, in a
TypeError: super() argument 1 must be type, not classobj

如果我更换class Xclass X(object),它会奏效。这有什么解释?


3
您的“但是我用类X(object)替换了类X”解决了我的问题!thanx
AliBZ

Answers:


132

原因是super()只能在新型类上运行,这在2.x系列中意味着从object

>>> class X(object):
        def a(self):
            print 'a'

>>> class Y(X):
        def a(self):
            super(Y, self).a()
            print 'b'

>>> c = Y()
>>> c.a()
a
b

4
从哪个python版本开始,这成为默认行为?
地理

6
2.2是在引入新样式类时,3.0成为默认类。
2009年

7
@tsunami如果您想进入超类,请做“ Xa(self)”
James Brady

我想你误解了我。三联画。我记得我使用的是低于3.0的python版本,我并没有特别指出我的类是从Object继承的,调用super的效果很好。也许是从2.6起的默认行为?只是说:)
地理位置

雪花石膏,真的没有必要。新型类具有巨大的好处,而不仅仅是超级。不应该推广旧式方法。
科迪·布罗西

14

另外,除非必须,否则不要使用super()。您可能会怀疑,使用新型类不是通用的“正确的事情”。

有时候,您可能期望多重继承,并且可能会想要多重继承,但是在您知道MRO的繁琐细节之前,最好不要去管它,并坚持:

 X.a(self)

2
是正确的,因为在我使用Python / Django的6个月中,我一直将super用作“一般的正确做法”?
philgo20

1
好吧,它本身不会对单一继承造成伤害(除了它有点慢),但是它也不会给您带来任何好处。您必须设计任何需要乘法继承(最显着__init__)的方法,以便以一种清晰合理的方式传递参数,否则当有人尝试使用您的类进行乘法继承时,您会遇到TypeError或更糟的调试问题。除非您真的设计过以这种方式支持MI(这很棘手),否则最好避免super这种方法对MI安全的隐含含义。
bobince 2010年

3

如果以上答案均未明确提及。您的父类需要继承自“对象”,这实际上会将其转变为新的样式类。

# python 3.x:
class ClassName(object): # This is a new style class
    pass

class ClassName: # This is also a new style class ( implicit inheritance from object )
    pass

# Python 2.x:
class ClassName(object): # This is a new style class
    pass

class ClassName:         # This is a old style class
    pass

抱歉,但是在Python 3.x中,您的第二个示例(隐式继承)在提到的问题的上下文中并没有真正起作用。
sophros

1

我尝试了各种Xa()方法;但是,它们似乎需要X的实例才能执行a(),所以我做了X()。a(self),这似乎比以前的回答更完整,至少对于我遇到的应用程序而言。由于不必要的构造和破坏,这似乎不是解决问题的好方法,但它可以正常工作。

我的特定应用程序是Python的cmd.Cmd模块,由于某种原因,它显然不是NewStyle对象。

最后结果:

X().a(self)
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.