Python super()引发TypeError

问题:Python super()引发TypeError

在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),它会奏效。这有什么解释?

In Python 2.5, the following code raises a 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

If I replace the class X with class X(object), it will work. What’s the explanation for this?


回答 0

原因是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

The reason is that super() only operates on new-style classes, which in the 2.x series means extending from 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

回答 1

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

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

 X.a(self)

In addition, don’t use super() unless you have to. It’s not the general-purpose “right thing” to do with new-style classes that you might suspect.

There are times when you’re expecting multiple inheritance and you might possibly want it, but until you know the hairy details of the MRO, best leave it alone and stick to:

 X.a(self)

回答 2

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

# 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

In case none of the above answers mentioned it clearly. Your parent class needs to inherit from “object”, which would essentially turn it into a new style class.

# 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

回答 3

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

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

最后结果:

X().a(self)

I tried the various X.a() methods; however, they seem to require an instance of X in order to perform a(), so I did X().a(self), which seems more complete than the previous answers, at least for the applications I’ve encountered. It doesn’t seem to be a good way of handling the problem as there is unnecessary construction and destruction, but it works fine.

My specific application was Python’s cmd.Cmd module, which is evidently not a NewStyle object for some reason.

Final Result:

X().a(self)