38

Say, I have a class Foo, extending class Bar. And I want to slightly override Foo's consructor. And I don't want even know what signarure of Bar's constructors is. Is there a way to do this?

If you didn't understand, I mean the following:

class Bar:
   def __init__ (self, arg1=None, arg2=None, ... argN=None):
      ....


class Foo (Bar):
    #Here i just want add additional parameter to constructor, but don't want to know anything about Bar's other parameters (arg1, arg2..., argN)
    def __init__ (self, my_new_arg=None, ??? )
       self.new_arg = my_new_arg
       Bar.__init__(self, ??? )

Is there a way to put something short and elegant instead of ??? in this code? (Maybe some variations of args/kwargs)

2
  • 2
    If Foo should know so little about Bar, why is it deriving from Bar? I mean, the given technique is a useful time-saver, but... Commented Nov 30, 2011 at 22:26
  • Note that __init__ is not the constructor, it's an initializer, even though it's usually used in the same way. Otherwise __init__ would be a @classmethod. Commented Nov 19, 2019 at 14:46

2 Answers 2

55
class Parent(object):
    def __init__(self, a, b):
        print 'a', a
        print 'b', b

class Child(Parent):
    def __init__(self, c, d, *args, **kwargs):
        print 'c', c
        print 'd', d
        super(Child, self).__init__(*args, **kwargs)

test = Child(1,2,3,4)

Output:

c 1
d 2
a 3
b 4
Sign up to request clarification or add additional context in comments.

2 Comments

Note that this answer should be updated for python 3.x users, which finally (although at this point, ages ago =) simplified the super call: def __init__(self, c, d, *args, **kwargs): super(*args, **kwargs). Unless you're dealing with multiple inheritance, python already knows the only possible superclass it should be using.
@Mike'Pomax'Kamermans You probably meant super().__init__(*args, **kwargs)?
11

The *args, **kwds solution presented by @Acorn is a good start (though I take issue with the *args part of the answer). This approach is presented with a number of refinements in the article, Python's Super Considered Super.

The *args part is ill-advised because it is doesn't allow you to insert new classes in the hierarchy and it precludes subclasses from using multiple inheritance with other classes that may have incompatible positional arguments. The **kwds approach works much better because it doesn't enforce a particular ordering of the call chain.

Also note, you can use named arguments to separate and remove the current method's named arguments from the rest of the keyword arguments before they get passed up the chain:

class Bar(object):
   def __init__(self, arg1=None, arg2=None, argN=None):
       print arg1, arg2, argN

class Foo(Bar):
    def __init__(self, my_new_arg=None, **kwds):
       super(Foo, self).__init__(**kwds)
       self.new_arg = my_new_arg
       print my_new_arg

f = Foo(my_new_arg='x', arg2='y')

Having each method strip-off the arguments it needs is important because a parent method such as object.__init__ expects no arguments at all.

One final note, if you're going to use super, be sure that your top most class is new-style (i.e. it inherits from object or some other builtin type).

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.