43

Are there situations where you want to do some processing before you call super()?

This is a contrived example. Are there better examples? Is this considered pythonic?

class Base(object):
    def __init__(self, name):
        print "Base %s created" % name
        self._name = name

class UpperBase(A):
    """ Similar to base but the name is in uppercase. """
    def __init__(self, name):
        name = name.upper() 
        super(UpperBase, self).__init__(name)
TomOnTime
  • 4,175
  • 4
  • 36
  • 39
  • 3
    Your example is *precisely* the kind of situation where you perform additional calculations before the upcall to the parent class. I know I do it quite often when defining `Thread` subclasses - I usually have some logic in there to give the thread a meaningful name based on the constructor arguments. – ncoghlan Apr 12 '11 at 12:57
  • 1
    I think you should avoid *modifying* the instance state before calling the `super()..` method. So just doing some calculations on the arguments (transforming, validating, etc) is OK but you should not alter the state of the instance. – frans Aug 30 '17 at 13:48
  • @frans Why? (I've seen plenty of code do it) – TomOnTime Aug 30 '17 at 14:23
  • On the one side it's some sort of gut feeling which I can't fully explain. Maybe it's easier to understand what's happening if the `super()` method is *always* being called before anything else happens (without any *exceptions* you'd have to explain. It also feels like strange architecture If you *need* to change the state of the instance before the base class' method can be called safely (which would be a semantic dependency from base class to derived class) – frans Aug 31 '17 at 07:30

1 Answers1

54

Sometimes you need to validate the arguments before calling super():

class UpperBase(Base):
    def __init__(self, name):
        if not name_valid(name):
            raise ValueError()
        super(UpperBase, self).__init__(name)

I don't see why this wouldn't be pythonic, because it's the easiest way to do it and it's straightforward. Also, read @JHSaunders' comment, he makes a good point.

Gabi Purcaru
  • 30,940
  • 9
  • 79
  • 95
  • 32
    Ya, the init method in python is not a constructor like C++, it does not do the actual memory allocation. By the time init is called the memory is allocated. So it is really just a normal method that happens to have certain semantics (It is called after an object is constructed). So in short you should be able to call it anywhere. (If I am wrong some one please correct me) – JHSaunders Apr 12 '11 at 11:26
  • 1
    In C++ the constructor does not allocate memory but initialize it and other things can be done there, too. There are indeed a lot of differences between C++ constructors and Python's `__init__()`-method but this question is about `super()` in general, not `super().__init__()` only. – frans Aug 31 '17 at 09:25
  • 6
    In Python 3, you can simply call `super()` rather than `super(UpperBase, self)`: https://docs.python.org/3/library/functions.html#super – phoenix Feb 14 '18 at 12:55