hayj hayj - 5 months ago 14
Python Question

Manage both args and kwargs in a python inheritance hierarchy

Are there any "good" way to manage both args and kwargs in a inheritance hierarchy like I tried in this code. I mean without to get a value with a specified key in kwargs or something like this...

It is supposed to display

1 2 3 4
:

class Parent(object):
def __init__(self, motherArg1, motherArg2=100):
self.motherArg1 = motherArg1
self.motherArg2 = motherArg2
def printParent(self):
print self.motherArg1
print self.motherArg2

class Child(Parent):
def __init__(self, childArg1, *args, childArg2=100, **kwargs): # Doesn't work here
super(Child, self).__init__(*args, **kwargs)
self.childArg1 = childArg1
self.childArg2 = childArg2
def printChild(self):
print self.childArg1
print self.childArg2

child = Child(1, 3, childArg2=2, motherArg2=4)
child.printChild()
child.printParent()


The syntax is not good : expected ");" after *args.

And
def __init__(self, childArg1, childArg2=100, *args, **kwargs)
is a right syntax but doesn't work.


  1. When I try this syntax and
    child = Child(1, childArg2=2, 3, motherArg2=4)
    , I get SyntaxError: non-keyword arg after keyword arg

  2. And when I try
    child = Child(1, 3, childArg2=2, motherArg2=4)
    I get TypeError: __init__() got multiple values for keyword argument 'childArg2'


Answer

when you rename printChild of the parent to printParent (and fix the prints) it already works in python 3, as suggested:

1
2
3
4

But you can get it to work for python2, too. You'd do this by removing entries in kwargs which are supposed to be relevant for the child before you pass them on to the parent.

Code (working for python3):

class Parent(object):
    def __init__(self, motherArg1, motherArg2=100):
        self.motherArg1 = motherArg1
        self.motherArg2 = motherArg2
    def printParent(self):
        print(self.motherArg1)
        print(self.motherArg2)

class Child(Parent):
    def __init__(self, childArg1, *args, childArg2=100, **kwargs): # Doesn't work here
        super(Child, self).__init__(*args, **kwargs)
        self.childArg1 = childArg1
        self.childArg2 = childArg2
    def printChild(self):
        print(self.childArg1)
        print(self.childArg2)

child = Child(1, 3, childArg2=2, motherArg2=4)
child.printChild()
child.printParent()

Code for python2

class Parent(object):
    def __init__(self, motherArg1, motherArg2=100):
        self.motherArg1 = motherArg1
        self.motherArg2 = motherArg2
    def printParent(self):
        print(self.motherArg1)
        print(self.motherArg2)

class Child(Parent):
    def __init__(self, childArg1, *args, **kwargs): # Doesn't work here
        if 'childArg2' in kwargs:
            childArg2 = kwargs['childArg2']
            del kwargs['childArg2']
        super(Child, self).__init__(*args, **kwargs)
        self.childArg1 = childArg1
        self.childArg2 = childArg2
    def printChild(self):
        print(self.childArg1)
        print(self.childArg2)

child = Child(1, 3, childArg2=2, motherArg2=4)
child.printChild()
child.printParent()
Comments