Python类中的super方法在多继承中的用法(一个例子看懂super()的使用方法)

Python类中如何调用父类?

  1. 直接写父类的名字
  2. 使用不带参数的super()方法
  3. 使用带参数的super(父类)方法

第1种方法比较简单,直接在调用的时候指定父类名称即可。但是这种直接使用的方式会有一个副作用,当存在多重继承的时候,父类的初始化方法会被多次调用。解决方法就是使用不带参数的super方法,该方法会使用一个D3算法,该算法会确保所有类的初始化方法仅仅调用一次。看例子:

class Parent(object):
    def __init__(self, name, *args, **kwargs):
        print("init Parent begin")
        self.name = name
        print("init Parent End")


class Son1(Parent):
    def __init__(self, name, gender, *args, **kwargs):
        print("init Son1 begin")
        self.gender = gender
        super().__init__(name, *args, **kwargs)
        print("init Son1 End")

class Son2(Parent):
    def __init__(self, name, age, *args, **kwargs):
        print("init Son2 begin")
        self.age = age
        super().__init__(name, *args, **kwargs)
        print("init Son2 End")

class Grandson(Son1, Son2):
    def __init__(self, name, gender, age):
        print("init Grandson begin")
        super().__init__(name, gender, age)
        print("init Grandson End")

print(Grandson.mro())

grandson = Grandson("zhangsan", "M", 23)
print("name = %s"%grandson .name)
print("gender = %s"%grandson .gender)
print("age = %s"%grandson .name)

输出结果如下:
[<class ‘main.Grandson’>, <class ‘main.Son1’>, <class ‘main.Son2’>, <class ‘main.Parent’>, <class ‘object’>]
上面的输出就是Grandson.mro()打印出来的对于多重继承调用super()时所采用的顺序,从下面的输出也可以跟上面进行对照,首先调用Grandson的初始化,然后调用Son1的初始化,再调用Son2的初始化,最后调用Parent的初始化。
init Grandson begin
init Son1 begin
init Son2 begin
init Parent begin
init Parent End
init Son2 End
init Son1 End
init Grandson End

如果把super都换成每个类的父类名,那么就可以得到下面的结果. 测试代码和结果如下,可以看到Parent被调用多次:

class Parent(object):
    def __init__(self, name, *args, **kwargs):
        print("init Parent begin")
        self.name = name
        print("init Parent End")


class Son1(Parent):
    def __init__(self, name, gender, *args, **kwargs):
        print("init Son1 begin")
        self.gender = gender
        super().__init__(name, *args, **kwargs)
        print("init Son1 End")

class Son2(Parent):
    def __init__(self, name, age, *args, **kwargs):
        print("init Son2 begin")
        self.age = age
        super().__init__(name, *args, **kwargs)
        print("init Son2 End")

class Grandson(Son1, Son2):
    def __init__(self, name, gender, age):
        print("init Grandson begin")
        super().__init__(name, gender, age)
        print("init Grandson End")

print(Grandson.mro())

grandson = Grandson("zhangsan", "M", 23)
print("name = %s"%grandson.name)
print("gender = %s"%grandson.gender)
print("age = %s"%grandson.age)

输出结果如下:
[<class ‘main.Grandson’>, <class ‘main.Son1’>, <class ‘main.Son2’>, <class ‘main.Parent’>, <class ‘object’>]
init Grandson begin
init Son1 begin
init Parent begin
init Parent End

init Son1 End
init Son2 begin
init Parent begin
init Parent End

init Son2 End
init Grandson End
name = zhangsan
gender = M
age = 23

如果继承的再多一些,Parent将被调用更多次,这是难以接受的,所以应该尽量使用super方法。

顺便说一句,supe()如果指定参数的话,会直接调用指定参数类的方法。将会打破MRO指定的默认顺序,跳转到对应类上去执行。

<think>好的,我现在要帮助用户理解面向对象编程的概念,特别是方法、多态这些部分。用户提到的是B站黑马程序员的Python600集课程中的内容,可能他们觉得课程中的解释不够清楚,或者自己刚接触这些概念,需要更直观的例子。 首先,我需要回忆下面向对象的基本概念。面向对象编程(OOP)是一种编程范式,用“对象”来设计软件。对象包含数据和操作数据的方法则是创建对象的蓝图,定义了对象的属性和方法。用户可能对和对象的关系不太清楚,所以我需要用一个简单的例子来说明,比如用动物生成猫和狗的对象。 接下来是方法方法是属于而不是实例的方法,通常用@classmethod装饰器定义,第一个参数是cls,指向本身。用户可能混淆了方法和实例方法的区别,需要举例说明,比如用方法创建特定型的对象。 然后是多态。多态指的是不同的对象对同一消息做出不同的响应。在Python中,多态通常通过继承方法重写实现。用户可能不明白为什么需要多态,或者如何在实际中使用,所以需要例子展示不同子对同一方法的不同实现。 用户需要例题代码,所以我得确保每个概念都有对应的代码示例。比如,定义一个动物,然后创建猫和狗的子,重写叫的方法来展示多态。方法例子可以用一个创建生日年份的方法。 需要注意代码的正确性,比如使用@classmethod和@staticmethod装饰器,以及继承时的super()用法。同时,代码要简洁,避免复杂的功能,让用户能专注于概念本身。 可能用户还会有其他疑问,比如静态方法方法的区别,或者多态在Python中的具体实现方式(因为Python是动态型,多态的实现与其他语言如Java不同)。但根据问题,可能暂时不需要深入这些细节,保持解释的简单易懂更重要。 最后,结构要清晰,分点解释每个概念,先理论后例子,帮助用户逐步构建理解。确保语言口语化,避免技术术语堆砌,用日常比辅助解释,比如把比作图纸,对象是根据图纸建造的房子。</think>我帮你用做奶茶店的例子拆解面向对象核心概念,配合代码+生活化案例,理解起来超轻松! 一、基础概念拆解(先看骨架) ```python # 1.与对象:模板与产品的关系 class 奶茶设备: def __init__(self, 品牌, 功率): self.品牌 = 品牌 # 属性:描述特征的变量 self.功率 = 功率 # 方法:对象的行为(函数) def 制作奶茶(self, ): print(f"用{self.品牌}设备制作一杯{型}奶茶") # 创建对象(实例化) 设备1 = 奶茶设备("喜茶联名款", 1500) 设备1.制作奶茶("珍珠") # 输出:用喜茶联名款设备制作一杯珍珠奶茶 ``` 二、方法 vs 静态方法(奶茶店运营统计) ```python class 奶茶店: 总营业额 = 0 # 属性(所有门店共享) def __init__(self, 店名): self.店名 = 店名 @classmethod def 更新营业额(cls, 金额): cls.总营业额 += 金额 # cls指向本身 @staticmethod def 计算成本(原料成本, 人工成本): return 原料成本 + 人工成本 # 与无关的工具函数 # 使用方法 奶茶店.更新营业额(5000) print(奶茶店.总营业额) # 输出:5000 # 使用静态方法 成本 = 奶茶店.计算成本(2000, 3000) print(f"总成本:{成本}元") # 输出:总成本:5000元 ``` 三、多态实战(不同奶茶加料方式) ```python class 基础奶茶: def 加料(self): print("加珍珠") class 芝士奶茶(基础奶茶): def 加料(self): # 方法重写(多态体现) print("加芝士奶盖") class 水果茶(基础奶茶): def 加料(self): print("加新鲜芒果") def 制作流程(奶茶): 奶茶型.加料() # 统一调用接口,不同表现 # 多态演示 制作流程(基础奶茶()) # 输出:加珍珠 制作流程(芝士奶茶()) # 输出:加芝士奶盖 制作流程(水果茶()) # 输出:加新鲜芒果 ``` 四、为什么需要面向对象?(现实优势) 1. 模块化管理:像搭积木一样组织代码(设备管理、订单处理、员工模块分开) 2. 降低复杂度:修改奶茶配方只需改动对应,不影响其他模块 3. 复用性强:开分店直接复用现有,只需调整参数 4. 扩展方便:新增奶茶品只需继承父类,符合开闭原则 关键记忆点: - = 设计图纸,对象 = 根据图纸造的房子 - 方法管全局(如统计所有门店销售额) - 实例方法管自己(如每台设备的工作状态) - 多态 ≈ 同样的指令(加料),不同对象有不同响应 理解了吗?试着写一个`咖啡机`,要求包含: 1. 属性记录总制作杯数 2. 实例属性包含咖啡机型号 3. 用多态实现`美式咖啡`和`卡布奇诺`的不同制作方法
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值