ChatGPT解决这个技术问题 Extra ChatGPT

Python super() raises TypeError

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?

your "however I replace class X with class X(object)" fixed my problem ! thanx

p
poke

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

From what python version did this become default behaviour ?
2.2 was when new-style classes were introduced, 3.0 is where they became the default.
@tsunami if you want to get at the superclass, do "X.a(self)"
I think you misunderstood me . Triptych . I remember I was using a python version less than 3.0 , and I didn't specifically said that my class inherits from Object , and the call to super worked . Maybe it's default behaviour from 2.6 ? Just saying :)
Alabaster, there's really no need for that. New-style classes have a huge number of benefits, not just super. Old-style ways shouldn't be promoted.
b
bobince

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)

is that correct because in my 6 months of Python/Django I've been using super as the "general right thing to do " ?
Well it doesn't hurt you for single inheritance in itself (except that it's a bit slower), but it doesn't get you anything on its own either. You have to design any methods that need to multiply-inherit (most notably __init__) to pass through arguments in a clean and sensible way, otherwise you'll get TypeErrors or worse debugging problems when someone tries to multiply-inherit using your class. Unless you've really designed to support MI in this way (which is quite tricky), it's probably better to avoid the implication super has that the method is MI-safe.
This seems like bad advice.
A
Abhi Tk

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

Sorry, but in Python 3.x your second example (implicit inheritance) does not really work in the context of the issue mentioned.
Z
Zoran Pavlovic

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)