Python多重继承中调用双亲的构造函数(一般情况)

问题描述 投票:0回答:2

我试图弄清楚Python中的多重继承,但我找到的所有文章都仅限于简单的情况。让我们考虑以下示例:

class Vehicle:
    def __init__(self, name: str) -> None:
        self.name = name
        print(f'Creating a Vehicle: {name}')

    def __del__(self):
        print(f'Deleting a Vehicle: {self.name}')


class Car(Vehicle):
    def __init__(self, name: str, n_wheels: int) -> None:
        super().__init__(name)
        self.wheels = n_wheels
        print(f'Creating a Car: {name}')

    def __del__(self):
        print(f'Deleting a Car: {self.name}')


class Boat(Vehicle):
    def __init__(self, name: str, n_props: int) -> None:
        super().__init__(name)
        self.propellers = n_props
        print(f'Creating a Boat: {name}')

    def __del__(self):
        print(f'Deleting a Boat: {self.name}')


class Amfibii(Car, Boat):
    def __init__(self, name: str, n_wheels: int, n_props: int) -> None:
        Car.__init__(self, name, n_wheels)
        Boat.__init__(self, name, n_props)
        print(f'Creating an Amfibii: {name}')

    def __del__(self):
        print(f'Deleting an Amfibii: {self.name}')


my_vehicle = Amfibii('Mazda', 4, 2)

我想了解调用构造函数和析构函数的顺序,以及“super”关键字的正确和一般用法。 在上面的示例中,我收到以下错误:

super().__init__(name)
类型错误:
Boat.__init__()
缺少 1 个必需的位置参数:'n_props'

我应该如何正确调用具有不同构造函数参数集的父母双方的构造函数?

python inheritance super diamond-problem
2个回答
1
投票

感谢评论和下面的文章,我明白了。 https://rhettinger.wordpress.com/2011/05/26/super-considered-super/

  1. 关于构造函数的参数,它们应该被命名。这样,每个级别都会剥离它需要的内容,并使用 super() 将其传递到下一个级别

  2. 每个类仅调用一次 super().init() 。 MRO 顺序中的以下类负责继续初始化。

更新的示例:

class Vehicle:
    def __init__(self, name: str) -> None:
        self.name = name
        print(f'Creating a Vehicle: {name}')

    def __del__(self):
        print(f'Deleting a Vehicle: {self.name}')

    def go(self):
        print('Somehow moving...')
        assert not hasattr(super(), 'go')


class Car(Vehicle):
    def __init__(self, n_wheels: int,  *args, **kwargs) -> None:
        super().__init__(*args, **kwargs)
        self.wheels = n_wheels
        print(f'Creating a Car: {self.name}')

    def __del__(self):
        print(f'Deleting a Car: {self.name}')

    def go(self):
        print('Riding...')
        super().go()


class Boat(Vehicle):
    def __init__(self, n_props, *args, **kwargs) -> None:
        super().__init__(*args, **kwargs)
        self.propellers = n_props
        print(f'Creating a Boat: {self.name}')

    def __del__(self):
        print(f'Deleting a Boat: {self.name}')

    def go(self):
        print('Swimming...')
        super().go()


class Amfibii(Car, Boat):
    def __init__(self, *args, **kwargs) -> None:
        super().__init__(*args, **kwargs)
        print(f'Creating an Amfibii: {self.name}')

    def __del__(self):
        print(f'Deleting an Amfibii: {self.name} with {self.wheels} wheels and {self.propellers} propellers')

    def go(self):
        print('Riding or swimming...')
        super().go()


my_vehicle = Amfibii(name='Mazda', n_wheels=4, n_props=2)
my_vehicle.go()

有点麻烦(委婉地说),不是吗?


0
投票

你可以这样做:

class Vehicle:
    def __init__(self, *args, **kwargs) -> None:
        self.name = kwargs['name']
        print(f'Creating a Vehicle: {self.name}')


class Car(Vehicle):
    def __init__(self, *args, **kwargs) -> None:
        super().__init__(*args, **kwargs)
        self.wheels = kwargs['n_wheels']
        print(f'Creating a Car: {self.name}')


class Boat(Vehicle):
    def __init__(self, *args, **kwargs) -> None:
        super().__init__(*args, **kwargs)
        self.propellers = kwargs['n_props']
        print(f'Creating a Boat: {self.name}')

    def __del__(self):
        print(f'Deleting a Boat: {self.name}')


class Amfibii(Car, Boat):
    def __init__(self, *args, **kwargs) -> None:
        super().__init__(*args, **kwargs)
        print(f'Creating an Amfibii: {self.name}')

    def __del__(self):
        print(f'Deleting an Amfibii: {self.name}')

注意:但我认为这是糟糕的编码风格!

© www.soinside.com 2019 - 2024. All rights reserved.