Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to override constructor of Python class with many arguments?

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)

like image 715
Alexander Avatar asked Nov 30 '11 21:11

Alexander


People also ask

How do you overload a class constructor in Python?

Use the @classmethod Decorators to Overload a Constructor in Python. The @classmethod decorator allows the function to be accessible without instantiating a class. Such methods can be accessed by the class itself and via its instances. When used in overloading, such functions are called factory methods.

Can you override constructor in Python?

Python constructor overriding mean one method will overrides the other. The parent class and child class both have the constructor and the child will override the parent constructor. After writing the above code (python constructor overriding) the output will appear as a “ This is Son class constructor”.

How many arguments can be passed to a constructor?

This method takes four arguments: the loan amount, the interest rate, the future value and the number of periods.

How do you pass a constructor argument in Python?

Creating the constructor in pythonWe can pass any number of arguments at the time of creating the class object, depending upon the __init__() definition. It is mostly used to initialize the class attributes. Every class must have a constructor, even if it simply relies on the default constructor.


2 Answers

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 
like image 177
Acorn Avatar answered Sep 28 '22 01:09

Acorn


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).

like image 20
Raymond Hettinger Avatar answered Sep 28 '22 00:09

Raymond Hettinger