109

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?

poke
  • 369,085
  • 72
  • 557
  • 602
Geo
  • 93,257
  • 117
  • 344
  • 520
  • 3
    your "however I replace class X with class X(object)" fixed my problem ! thanx – AliBZ May 24 '13 at 17:35
  • Does this answer your question? [super() fails with error: TypeError "argument 1 must be type, not classobj" when parent does not inherit from object](https://stackoverflow.com/questions/1713038/super-fails-with-error-typeerror-argument-1-must-be-type-not-classobj-when) – sophros Jan 30 '20 at 15:23

4 Answers4

133

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
poke
  • 369,085
  • 72
  • 557
  • 602
Serafina Brocious
  • 30,433
  • 12
  • 89
  • 114
  • 4
    From what python version did this become default behaviour ? – Geo Jan 28 '09 at 20:51
  • 7
    2.2 was when new-style classes were introduced, 3.0 is where they became the default. – Serafina Brocious Jan 28 '09 at 20:54
  • 7
    @tsunami if you want to get at the superclass, do "X.a(self)" – James Brady Jan 28 '09 at 20:54
  • 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 :) – Geo Jan 28 '09 at 20:55
  • 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. – Serafina Brocious Jan 28 '09 at 20:56
  • Tsunami, You're quite likely right. 2.6 is meant as a half-way to 3.0 and it would make sense for them to make it the default there. However, you'll have to check the docs on that. – Serafina Brocious Jan 28 '09 at 20:56
  • Thanks for the quick response Cody ! Thanks for the comments guys ! – Geo Jan 28 '09 at 20:58
14

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)
bobince
  • 528,062
  • 107
  • 651
  • 834
  • 2
    is that correct because in my 6 months of Python/Django I've been using super as the "general right thing to do " ? – philgo20 Apr 07 '10 at 16:06
  • 1
    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. – bobince Apr 07 '10 at 17:36
  • This seems like bad advice. – Boris Verkhovskiy May 03 '21 at 20:58
3

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
Abhi Tk
  • 91
  • 7
  • Sorry, but in Python 3.x your second example (implicit inheritance) does not really work in the context of the issue mentioned. – sophros Jan 30 '20 at 15:23
1

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)
Zoran Pavlovic
  • 1,166
  • 2
  • 23
  • 38
weberc2
  • 7,423
  • 4
  • 41
  • 57