问答详情
源自:3-4 Python中的多态

关于多重继承在子类的__init__方法中到底应该调用哪个父类的__init__

我想问下 假设 C继承了A和B  其中A的init有两个参数,B的init有三个参数,这几个参数都没有啥特别的关系,然后我在写C的init函数的时候,里面的super应该咋写,到底以哪个父类的为准。这块儿我比较疑惑。

提问者:程序猿_郭文超 2023-10-08 17:10

个回答

  • qq_青萍之末_2
    2024-06-09 18:51:04

    # 关于你这个情况,我尝试了两种理解方法,我自己称为显示调用和继承式调用,具体代码如下:


    class Person(object):

        def __init__(self, name, gender):

            self.name = name

            self.gender = gender



    class Student(Person):

        def __init__(self, name, gender, score):

            super(Student, self).__init__(name, gender)

            self.score = score



    class Teacher(Person):

        def __init__(self, name, gender, course):

            super(Teacher, self).__init__(name, gender)

            self.course = course



    class Skill(object):

        def __init__(self, sport):

            self.sport = sport



    class PlayBasketball(Skill):

        def __init__(self, sport):

            super(PlayBasketball, self).__init__(sport)



    class PlayFootball(Skill):

        def __init__(self, sport):

            super(PlayFootball, self).__init__(sport)



    # 显示地调用父类的init初始化方法

    class StudentBasketball(PlayBasketball, Student):

        def __init__(self, name, gender, score, sport):

            Student.__init__(self, name, gender, score)

            PlayBasketball.__init__(self, sport)


        def can_play(self):

            return 'I am %s ,i am %s, i got score %s ,i can play%s' % (self.name, self.gender, self.score, self.sport)



    # 显示地调用父类的init初始化方法

    class TeacherFootball(PlayFootball, Teacher):

        def __init__(self, name, gender, course, sport):

            Teacher.__init__(self, name, gender, course)

            PlayFootball.__init__(self, sport)


        def can_play(self):

            return 'I am %s ,i am %s,i teach %s ,i can play%s' % (self.name, self.gender, self.course, self.sport)



    # 继承式地调用父类的init初始化方法

    class StudentPlayBasketball(PlayBasketball, Student):

        def __init__(self, name, gender, score, sport):

            super(StudentPlayBasketball, self).__init__(name, gender, score)

            super(StudentPlayBasketball, self).__init__(sport)


        def can_play(self):

            return 'I am %s ,i am %s, i got score %s ,i can play%s' % (self.name, self.gender, self.score, self.sport)



    # 继承式地调用父类的init初始化方法

    class TeacherPlayFootball(PlayFootball, Teacher):

        def __init__(self, name, gender, course, sport):

            super(TeacherPlayFootball, self).__init__(name, gender, course)

            super(TeacherPlayFootball, self).__init__(sport)


        def can_play(self):

            return 'I am %s ,i am %s,i teach %s ,i can play%s' % (self.name, self.gender, self.course, self.sport)



    student = StudentBasketball('Jason', 'Male', 98, 'Basketball')

    teacher = TeacherFootball('Alice', 'Female', 'English', 'Football')


    student1 = StudentBasketball('Jason', 'Male', 98, 'Basketball')

    teacher2 = TeacherFootball('Alice', 'Female', 'English', 'Football')


    print(student1.can_play())

    print(teacher2.can_play())


  • slongzhang
    2024-03-21 22:11:34

    在Python中,当类C继承自类A和类B,并且A和B的__init__方法需要不同数量的参数时,你需要在类C的__init__方法中显式地调用这两个父类的__init__方法。由于Python的super()函数用于调用父类的方法,但它不会自动处理不同数量的参数问题,因此你需要手动调用每个父类的__init__方法,并传递必要的参数。

    以下是一个例子,展示了如何在类C的__init__方法中调用类A和类B的__init__方法:

    class A:  
        def __init__(self, name, age):  
            self.name = name  
            self.age = age  
      
    class B:  
        def __init__(self, name, sex, height):  
            self.name = name  
            self.sex = sex  
            self.height = height  
      
    class C(A, B):  
        def __init__(self, name, age, sex, height):  
            # 显式调用A的__init__方法  
            A.__init__(self, name, age)  
            # 显式调用B的__init__方法  
            B.__init__(self, name, sex, height)  
      
    # 创建C的实例  
    c = C("Alice", 30, "female", 165)  
    print(c.name)  # 输出: Alice  
    print(c.age)   # 输出: 30  
    print(c.sex)   # 输出: female  
    print(c.height) # 输出: 165

    在上面的例子中,类C的__init__方法接受所有必要的参数,然后分别调用类A和类B的__init__方法。注意,这里我们直接调用了A和B的__init__方法,而不是使用super()。这是因为super()用于调用当前类在MRO(方法解析顺序)中的下一个父类的方法,但它不会处理不同数量的参数问题。由于类A和类B的__init__方法需要不同的参数集,直接调用它们是最直接和清晰的方式。

    如果你坚持想要使用super(),那么你必须确保你的继承结构以及__init__方法的参数设计允许这样做。这通常意味着你需要设计一个统一的参数列表,这个列表可以包含所有父类__init__方法所需的参数。然而,在你的情况下,由于参数之间没有直接的关系,并且它们各自属于不同的父类,这可能会变得非常复杂且不直观。因此,直接调用每个父类的__init__方法通常是更合适的选择。


  • 慕虎3120260
    2023-11-07 14:18:06

    我所理解的格式是这样的,希望对你有帮助:

    class 本类名(父类名)

        del __init__(所有属性(包括新属性)):

            super (本类名,self).__init__(父类拥有的属性)

            self.新属性1 = 新属性1