Python 继承和多态

Python 里的继承和多态是面向对象编程(OOP)的核心概念,学好了能让你的代码更灵活、可复用,还能少写不少重复代码。

参考文章:Python 继承和多态 | 简单一点学习 easyeasy.me

1. 什么是继承?

继承的基本概念

继承就是让一个类(子类)“继承”另一个类(父类)的属性和方法。子类可以直接用父类的功能,还能根据需要扩展或修改。打个比方,父类就像是“模板”,子类是基于模板再加工的“定制版”。

为什么需要继承

  • 代码复用:不用重复写相同的代码,父类的功能直接拿来用。
  • 逻辑清晰:把通用的功能放父类,子类只管自己的“个性”部分。
  • 扩展性强:子类可以加新功能,也可以改父类的行为。

Python 中类的基本定义回顾

在 Python 里,类用 class 关键字定义,属性是类的“变量”,方法是类的“函数”。来看个简单例子:

class Animal:
    def __init__(self, name):
        self.name = name
    
    def speak(self):
        return f"{self.name} 发出声音"

# 创建一个实例
dog = Animal("小狗")
print(dog.speak())  # 输出:小狗 发出声音

2. 单继承的实现

定义父类和子类

Python 的继承很简单,子类在定义时括号里写上父类的名字。子类会自动拥有父类的属性和方法。

class Animal:  # 父类
    def __init__(self, name):
        self.name = name
    
    def speak(self):
        return f"{self.name} 发出声音"

class Dog(Animal):  # 子类,继承 Animal
    pass

# 测试
dog = Dog("旺财")
print(dog.speak())  # 输出:旺财 发出声音

Dog 啥也没干,但因为继承了 Animal,它直接能用 speak 方法。

子类如何调用父类的方法和属性

子类可以用 super() 来调用父类的 __init__ 或其他方法,方便在子类里扩展父类的功能。

class Dog(Animal):
    def __init__(self, name, breed):
        super().__init__(name)  # 调用父类的 __init__
        self.breed = breed  # 子类新增属性
    
    def speak(self):  # 重写父类方法
        return f"{self.name} 汪汪叫"

# 测试
dog = Dog("旺财", "哈士奇")
print(dog.speak())  # 输出:旺财 汪汪叫
print(dog.breed)    # 输出:哈士奇

方法重写(Override)

子类可以“重写”父类的方法,改成自己的逻辑。像上面例子,Dog 重写了 speak,让它输出“汪汪叫”而不是“发出声音”。


3. 多继承和 MRO

什么是多继承

Python 允许一个类同时继承多个父类,这叫多继承。听起来很酷,但用不好容易把代码搞乱。来看例子:

class Flyer:
    def fly(self):
        return "我在飞!"

class Swimmer:
    def swim(self):
        return "我在游!"

class Duck(Animal, Flyer, Swimmer):  # 鸭子继承了三个类
    def __init__(self, name):
        super().__init__(name)

# 测试
duck = Duck("唐老鸭")
print(duck.speak())  # 输出:唐老鸭 发出声音
print(duck.fly())    # 输出:我在飞!
print(duck.swim())   # 输出:我在游!

Duck 继承了 AnimalFlyerSwimmer,所以它会叫、会飞、会游。

Python 的方法解析顺序(MRO)

多继承时,如果多个父类有同名方法,Python 得决定用哪个。这靠 MRO(Method Resolution Order) 来搞定。MRO 决定了方法查找的顺序,用的是 C3 线性化算法。

你可以用 类名.__mro__ 看 MRO 顺序:

print(Duck.__mro__)
# 输出:
# (<class '__main__.Duck'>, <class '__main__.Animal'>, <class '__main__.Flyer'>, 
#  <class '__main__.Swimmer'>, <class 'object'>)

Python 会按这个顺序找方法,super() 也会按这个顺序调用父类方法。

多继承的注意事项

  • 避免复杂继承:多继承容易让代码逻辑混乱,能用单继承就别用多继承。
  • 小心同名方法:如果多个父类有同名方法,确保 MRO 顺序是你想要的。
  • 用 super() 谨慎:多继承下,super() 的行为可能不符合直觉,建议明确调用父类方法。

4. 多态的概念和实现

什么是多态

多态就是“一种接口,多种实现”。简单说,不同的类可以用同样的方法名,但行为各不相同。多态让代码更灵活,调用方不用管具体是哪个类,只要方法名对就行。

Python 中多态的实现方式

Python 是动态语言,天然支持多态,不需要像 Java 那样的接口或抽象类。只需要不同类有同名方法,就能实现多态。

class Cat(Animal):
    def speak(self):
        return f"{self.name} 喵喵叫"

class Cow(Animal):
    def speak(self):
        return f"{self.name} 哞哞叫"

# 多态测试
animals = [Dog("旺财", "哈士奇"), Cat("咪咪"), Cow("大黄")]
for animal in animals:
    print(animal.speak())

输出:

旺财 汪汪叫
咪咪 喵喵叫
大黄 哞哞叫

这里 DogCatCow 都继承了 Animal,但 speak 方法各有不同。调用时只管 speak(),不用管具体是哪种动物,这就是多态。

多态的实际例子

假设我们要写一个“动物表演”程序,动物种类可能随时加新种类。多态可以让我们轻松扩展:

def animal_show(animal):
    print(f"表演开始:{animal.speak()}")

# 测试
animal_show(Dog("旺财", "哈士奇"))  # 输出:表演开始:旺财 汪汪叫
animal_show(Cat("咪咪"))            # 输出:表演开始:咪咪 喵喵叫

animal_show 函数只关心 animal 有没有 speak 方法,完全不care具体是什么类。


5. 继承和多态的实际应用

什么时候用继承和多态

  • 继承:当你有一堆类有共同的属性或方法时,抽个父类出来,把共性放进去。比如,DogCat 都有 namespeak,就适合用继承。
  • 多态:当你希望用统一的接口处理不同类型的对象时,用多态。比如,前面例子里的 animal_show 函数,能处理任何有 speak 方法的对象。

常见的设计模式场景

  • 工厂模式:用一个工厂类根据输入创建不同子类的对象,调用时只用统一接口。
  • 策略模式:通过多态实现不同策略,比如不同动物的叫声。
  • 模板方法:父类定义流程,子类实现具体步骤。

例子(模板方法):

class Game:
    def play(self):
        self.start()
        self.play_round()
        self.end()

    def start(self):
        print("游戏开始")
    
    def play_round(self):
        pass  # 子类实现
    
    def end(self):
        print("游戏结束")

class Chess(Game):
    def play_round(self):
        print("下棋中...")

class CardGame(Game):
    def play_round(self):
        print("打牌中...")

# 测试
chess = Chess()
chess.play()
# 输出:
# 游戏开始
# 下棋中...
# 游戏结束

注意事项和陷阱

  • 不要滥用继承:继承层级太深会让代码难维护,优先考虑组合(has-a 关系)而不是继承(is-a 关系)。
  • 多态要简单:方法名一致不代表逻辑一致,确保多态的接口语义清晰。
  • 小心 super():尤其在多继承时,super() 可能调用到意外的父类。
  • 性能考虑:继承和多态虽然方便,但深层继承链可能影响性能,特别是在大项目里。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值