Home > Software design >  Diamond problem with constructor - Python
Diamond problem with constructor - Python

Time:05-07

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?

CodePudding user response:

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.

CodePudding user response:

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'

CodePudding user response:

After changing to: ''' ws = WorkingStudent("Tony", "Soprano", 123, "F", "worker", 2400) '''

Traceback (most recent call last): 
ws = WorkingStudent("Tony", "Soprano", 123, "F", "worker", 2400) Student.__init__(self, firstName, lastName, Id, grades)_ super().__init__(firstName, lastName) 
TypeError: __init__() missing 2 required positional arguments: 'title' and 'salary'
  • Related