如何创建具有多重继承的类

Vis*_*tar 9 python oop multiple-inheritance python-3.x

我有这个代码:

class Person:
    def __init__(self, name, last_name, age):
        self.name = name
        self.last_name = last_name
        self.age = age 

class Student(Person):
    def __init__(self, name, last_name, age, indexNr, notes):
        super().__init__(name, last_name, age)
        self.indexNr = indexNr
        self.notes = notes

class Employee(Person):
    def __init__(self, name, last_name, age, salary, position):
        super().__init__(name, last_name, age)
        self.salary = salary
        self.position = position

class WorkingStudent(Student, Employee):
    def __init__(self, name, last_name, age, indexNr, notes, salary, position):
        Student.__init__(name, last_name, age, indexNr, notes)
        Employee.__init__(name, last_name, age, salary, position)
Run Code Online (Sandbox Code Playgroud)

我想创建一个像这样的WorkingStudent实例:

ws = WorkingStudent("john", "brown", 18, 1, [1,2,3], 1000, 'Programmer')
Run Code Online (Sandbox Code Playgroud)

但它不起作用,我收到此错误:

class Person:
    def __init__(self, name, last_name, age):
        self.name = name
        self.last_name = last_name
        self.age = age 

class Student(Person):
    def __init__(self, name, last_name, age, indexNr, notes):
        super().__init__(name, last_name, age)
        self.indexNr = indexNr
        self.notes = notes

class Employee(Person):
    def __init__(self, name, last_name, age, salary, position):
        super().__init__(name, last_name, age)
        self.salary = salary
        self.position = position

class WorkingStudent(Student, Employee):
    def __init__(self, name, last_name, age, indexNr, notes, salary, position):
        Student.__init__(name, last_name, age, indexNr, notes)
        Employee.__init__(name, last_name, age, salary, position)
Run Code Online (Sandbox Code Playgroud)

或者我在这里做错了什么?另外,我已经super()在WorkingStudent类中尝试过,但它仅调用第一个传递的类的构造函数。即在这种情况下Student

注意:我已经进行了多次 StackOverflow 查询,但找不到任何可以回答这个问题的内容。(或者也许我错过了)。

cot*_*ail 10

super()使用mro 传递参数,而不是显式类:

class Person:
    def __init__(self, name, last_name, age):
        self.name = name
        self.last_name = last_name
        self.age = age 

class Student(Person):
    def __init__(self, name, last_name, age, indexNr, notes, salary, position):
        # since Employee comes after Student in the mro, pass its arguments using super
        super().__init__(name, last_name, age, salary, position)
        self.indexNr = indexNr
        self.notes = notes

class Employee(Person):
    def __init__(self, name, last_name, age, salary, position):
        super().__init__(name, last_name, age)
        self.salary = salary
        self.position = position

class WorkingStudent(Student, Employee):
    def __init__(self, name, last_name, age, indexNr, notes, salary, position):
        # pass all arguments along the mro
        super().__init__(name, last_name, age, indexNr, notes, salary, position)

# uses positional arguments            
ws = WorkingStudent("john", "brown", 18, 1, [1,2,3], 1000, 'Programmer')
# then you can print stuff like
print(f"My name is {ws.name} {ws.last_name}. I'm a {ws.position} and I'm {ws.age} years old.")
# My name is john brown. I'm a Programmer and I'm 18 years old.
Run Code Online (Sandbox Code Playgroud)

检查先生:

WorkingStudent.__mro__
(__main__.WorkingStudent,
 __main__.Student,
 __main__.Employee,
 __main__.Person,
 object)
Run Code Online (Sandbox Code Playgroud)

当您创建WorkingStudent 的实例时,最好传递关键字参数,这样您就不必担心弄乱参数的顺序。

由于WorkingStudent将属性的定义推迟到父类,因此立即使用层次结构向上传递所有参数,super().__init__(**kwargs)因为子类不需要知道它不处理的参数。第一个父类是 Student,因此 self.IndexNr 等定义在那里。mro 中的下一个父类是 Employee,因此从 Student 中,将剩余的关键字参数传递给它,super().__init__(**kwargs)再次使用。从 Employee 中,定义在那里定义的属性,并super().__init__(**kwargs)再次通过 mro(到 Person)传递其余的属性。

class Person:
    def __init__(self, name, last_name, age):
        self.name = name
        self.last_name = last_name
        self.age = age 

class Student(Person):
    def __init__(self, indexNr, notes, **kwargs):
        # since Employee comes after Student in the mro, pass its arguments using super
        super().__init__(**kwargs)
        self.indexNr = indexNr
        self.notes = notes

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

class WorkingStudent(Student, Employee):
    def __init__(self, **kwargs):
        # pass all arguments along the mro
        super().__init__(**kwargs)

# keyword arguments (not positional arguments like the case above)
ws = WorkingStudent(name="john", last_name="brown", age=18, indexNr=1, notes=[1,2,3], salary=1000, position='Programmer')
Run Code Online (Sandbox Code Playgroud)