Q:

super constructor use *args and **kwargs for __init__

Say we have a base class Person and a subclass Employee (see code at the bottom).
After coding a while, I found I need to add more attributes to base:
class Person:

    def __init__(self, first, last, new_att1, new_att2):

Then I need to goto subclass, modify to following:
class Employee(Person):

    def __init__(self, first, last, new_att1, new_att2, staffnum):
        Person.__init__(first, last,  new_att1, new_att2)
        self.staffnumber = staffnum

Say I have 5 subclasses. Each time I update the base class attribute, I need to repeat above for all 5 subclasses. Anyone can help to point out an elegant way to manage it?
Original class:
class Person:

    def __init__(self, first, last):
        self.firstname = first
        self.lastname = last

    def __str__(self):
        return self.firstname + " " + self.lastname

class Employee(Person):

    def __init__(self, first, last, staffnum):
        Person.__init__(first, last)
        self.staffnumber = staffnum

A:

One option is to use keyword arguments only (which is a good idea anyway when you have many arguments):
class Person(object):
    def __init__(self, firstname, lastname, new_att1, new_att2):
        self.firstname = firstname
        self.lastname = lastname

    def __str__(self):
        return "%s %s" % (self.firstname, self.lastname)

class Employee(Person):
    def __init__(self, staffnumber, **kwargs):
        super(Employee, self).__init__(**kwargs)
        self.staffnumber = staffnumber

e = Employee(
    firstname="Foo",
    lastname="Bar",
    staffnumber=42,
    new_att1=True,
    new_att2=False,
)

The downside is that the subclass constructors don't have an explicit signature any more, which makes them harder to read and reason about.

