'Diamond problem with constructor - Python

I have a problem with the constructor of the WorkingStudent class:

class Person:
    def __init__ (self, firstName, lastName):
        self.firstName = firstName
        self.lastName = lastName

class Student(Person):
    def __init__(self, firstName, lastName, Id, grades):
        super().__init__(firstName, lastName)
        self.Id = Id
        self.grades = grades

class Worker(Person):
    def __init__(self, firstName, lastName, title, salary):
        super().__init__(firstName, lastName)
        self.title = title
        self.salary = salary

class WorkingStudent(Student, Worker):
    def __init__(self, firstName, lastName, Id, grades, title, salary):
        Student.__init__(self, firstName, lastName, Id, grades)
        Worker.__init__(self, firstName, lastName, title, salary)


ws = Worker("Tony", "Soprano", 123, "F")
ws.title="worker"
ws.salary=2400

When I try to create a class object this way:

ws = Worker("Tony", "Soprano", 123, "F", "worker", 2400)

I get error:

TypeError: __init__() takes 5 positional arguments but 7 were given

How should I create a constructor of WorkingStudent class?



Solution 1:[1]

Seems like you're trying to create a "working student" by initialising a "worker" class instance?

The worker class takes 5 arguments (including the self argument), whereas the workingstudent class takes 7. You're now giving self + 6 arguments to the Worker class...

Try changing

ws = Worker("Tony", "Soprano", 123, "F", "worker", 2400)

to

ws = WorkingStudent("Tony", "Soprano", 123, "F", "worker", 2400)

==EDIT==

Please see https://stackoverflow.com/a/46200507/7549479

The class signatures should be consistent, so you can use **kwargs to let every class accept (ignored) keyword arguments.

Solution 2:[2]

Not perfect, but it works:

class Person:
    def __init__ (self, firstName, lastName):
        self.firstName = firstName
        self.lastName = lastName

class Student(Person):
    def __init__(self, Id, grades, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.Id = Id
        self.grades = grades

class Worker(Person):
    def __init__(self, title, salary, *args, **kwargs):
        super().__init__(*args, *kwargs)
        self.title = title
        self.salary = salary

class WorkingStudent(Student, Worker):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

ws = WorkingStudent(123, "F", "title", 2400, "Tony", "Soprano")

ws2 = WorkingStudent(firstName="Tony", lastName="Soprano", Id="123", title="worker", salary=2400, grades="F")

In ws I need to give the arguments in this order! -> It works

In ws2 printing firstName and lastName gives 'firstName' and 'lastName' not 'Tony' and 'Soprano'

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 LadySylwia