3

I'm trying to use super() for a simple class hierarchy in this manner:

class Employee(object):
    def __init__(self, name):
        self.name = name

class FullTime(Employee):
    def __init__(self, name, satOff, freeDays=[], alDays=[], programDays=[]):
        global satsOffDict
        global dayDict
        super(Employee, self).__init__(name)

However, I'm getting this error:

TypeError: object.__init__() takes no parameters

I've read that you need to make the parent object type object (new style classes) in order for super to work. If I change class Employee(object) to class Employee(), I get this error:

TypeError: must be type, not classobj

What's going on?

user1427661
  • 11,158
  • 28
  • 90
  • 132
  • 2
    You might want to be careful passing lists as the defaults the `__init__` like that. That's just begging for interesting behavior ... http://stackoverflow.com/questions/1132941/least-astonishment-in-python-the-mutable-default-argument – mgilson Jan 09 '13 at 16:53

2 Answers2

7

You use the current class in super():

super(FullTime, self).__init__(name)

super() looks for requested methods relative to the first argument; you started the search from Employee instead, looking for the parent classes; object.__init__() is the next parent method that matches in that case.

You need to use the current class, because Python needs to search the base classes in Method Resolution Order; that ordering depends on how your current class is derived from it's base classes (especially if there is multiple inheritence or a base class ends up being referenced multiple times).

On Python 3.x, you can use super() without any arguments, and the compiler will add an extra hint to your method so that it can determine the correct class to start from.

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
  • 1
    Could you comment on why this is? I've always wondered. It seems as though the derived class should be trivially easy to identify automatically by the interpreter. Is there a use case for using something different as the first parameter? – acjay Jan 09 '13 at 16:45
  • 1
    Note that in 3.x, `super()` can take no arguments and work fine. – Gareth Latty Jan 09 '13 at 16:45
  • @acjohnson55: The MRO of the base classes depend on the inheriting class. Imagine a class that inherits from *two* super classes. – Martijn Pieters Jan 09 '13 at 16:45
  • So, you're saying that you can use a base class in ``super``, but then a compatible method better be in *the base class's* superclass lineage someplace? – acjay Jan 09 '13 at 16:49
  • @acjohnson55: Exactly. And it might be the wrong one, if there was a different MRO path to follow based on your current class. – Martijn Pieters Jan 09 '13 at 16:50
  • Okay, cool. Man, it really seems as though it would have made so much more sense to just make the first argument optional. I would go out on a limb and say the overwhelming majority of invocations of ``super`` are for situations where normal MRO is perfectly fine. – acjay Jan 09 '13 at 17:01
  • @acjohnson55: Explicit is better than implicit though. But sometimes practicality beats purity, so the no-args `super()` option was added in Python 3. – Martijn Pieters Jan 09 '13 at 17:03
  • I mean, if we like explicit so much, why not go back to static typing and C++ style generics? Or we can always just write in assembly :) Thanks for the info, though – acjay Jan 09 '13 at 18:55
2

When you use super in Python, you should be specifying the derived type (that is, the class in which you're writing the call) as the first parameter.

super(FullTime, self).__init__(name)
Platinum Azure
  • 45,269
  • 12
  • 110
  • 134