Python 继承详解(继承作用语法)

 更新时间:2025年07月10日 10:39:16   作者:江湖一条鱼  
继承是面向对象编程(OOP)的一个重要特性,允许一个类(子类)从另一个类(父类)继承属性和方法,继承可以提高代码的重用性,增强程序的可扩展性和可维护性,本文给大家介绍Python 继承的相关知识,感兴趣的朋友一起看看吧

继承是面向对象编程(OOP)的一个重要特性,允许一个类(子类)从另一个类(父类)继承属性和方法。继承可以提高代码的重用性,增强程序的可扩展性和可维护性。

一、继承的作用

  1. 代码复用
    子类继承父类的属性和方法,无需重复编写相同代码。

  2. 逻辑层次清晰
    通过继承关系表达对象间的从属关系,使代码更具结构性。

  3. 增强扩展性
    子类可以在继承父类的基础上扩展新的属性或方法,支持功能扩展。

  4. 多态性
    子类可以重写父类的方法,实现不同的行为。

二、继承的语法

在 Python 中,继承通过类定义时括号中的父类名实现。

1. 单继承

子类继承单个父类:

class Parent:
    def greet(self):
        print("Hello from Parent")
class Child(Parent):
    pass  # 子类继承了 Parent 的所有属性和方法
# 使用子类
child = Child()
child.greet()  # 输出: Hello from Parent

2. 多继承

子类继承多个父类:

class Parent1:
    def greet(self):
        print("Hello from Parent1")
class Parent2:
    def greet(self):
        print("Hello from Parent2")
class Child(Parent1, Parent2):
    pass
child = Child()
child.greet()  # 输出: Hello from Parent1 (根据继承顺序)

多继承会按照方法解析顺序(MRO)决定调用哪个父类的方法,可用 Class.mro()help(Class) 查看。

三、子类扩展

子类可以添加新的属性和方法,或者重写父类的方法。

1. 添加新功能

class Parent:
    def greet(self):
        print("Hello from Parent")
class Child(Parent):
    def say_goodbye(self):
        print("Goodbye from Child")
child = Child()
child.greet()       # 输出: Hello from Parent
child.say_goodbye()  # 输出: Goodbye from Child

2. 重写父类方法

通过在子类中重新定义方法,覆盖父类的同名方法。

class Parent:
    def greet(self):
        print("Hello from Parent")
class Child(Parent):
    def greet(self):
        print("Hello from Child")  # 重写父类方法
child = Child()
child.greet()  # 输出: Hello from Child

3. 调用父类方法

使用 super() 调用父类方法:

class Parent:
    def greet(self):
        print("Hello from Parent")
class Child(Parent):
    def greet(self):
        super().greet()  # 调用父类方法
        print("Hello from Child")
child = Child()
child.greet()
# 输出:
# Hello from Parent
# Hello from Child

四、继承的特殊情况

1. 子类初始化父类

如果父类有 __init__ 方法,子类需要显式调用它。

class Parent:
    def __init__(self, name):
        self.name = name
class Child(Parent):
    def __init__(self, name, age):
        super().__init__(name)  # 调用父类的初始化方法
        self.age = age
child = Child("Alice", 10)
print(child.name)  # 输出: Alice
print(child.age)   # 输出: 10

2. 方法解析顺序(MRO)

多继承时,Python 按 MRO 顺序查找方法。

class A:
    def show(self):
        print("A")
class B(A):
    def show(self):
        print("B")
class C(A):
    pass
class D(B, C):
    pass
print(D.mro())
# 输出: [<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>]
d = D()
d.show()  # 输出: B

五、抽象类与接口

通过继承实现抽象类和接口功能。

1. 抽象类

使用 abc 模块定义抽象类,要求子类必须实现特定方法。

from abc import ABC, abstractmethod
class AbstractClass(ABC):
    @abstractmethod
    def abstract_method(self):
        pass
class ConcreteClass(AbstractClass):
    def abstract_method(self):
        print("Implementation of abstract method")
obj = ConcreteClass()
obj.abstract_method()  # 输出: Implementation of abstract method

2. 接口

通过继承实现类似接口的功能,强制子类遵循某些规则:

class Interface:
    def method(self):
        raise NotImplementedError("Subclasses must implement this method")
class Implementation(Interface):
    def method(self):
        print("Method implemented")
obj = Implementation()
obj.method()  # 输出: Method implemented

 3. ABC类

from abc import ABC, abstractmethod, abstractclassmethod, abstractstaticmethod, abstractproperty
  1. ABC
    这是所有抽象基类的基类。

  2. @abstractmethod 装饰器
    用于定义抽象方法。子类必须实现该方法,否则无法实例化。

  3. @abstractclassmethod@abstractstaticmethod@abstractproperty
    用于定义抽象的类方法、静态方法和属性。

抽象基类不能直接实例化,必须由子类实现所有抽象方法后才能实例化。所以上述的AbstractClass类不能直接实例化,必须由ConcreteClass继承后实例化。

 4. 使用方法

1. 定义抽象基类

from abc import ABC, abstractmethod
# 定义抽象基类
class Shape(ABC):
    @abstractmethod
    def area(self):
        """计算面积"""
        pass
    @abstractmethod
    def perimeter(self):
        """计算周长"""
        pass
# 子类必须实现所有抽象方法
class Rectangle(Shape):
    def __init__(self, width, height):
        self.width = width
        self.height = height
    def area(self):
        return self.width * self.height
    def perimeter(self):
        return 2 * (self.width + self.height)
# 实例化子类
rect = Rectangle(5, 10)
print(rect.area())       # 输出: 50
print(rect.perimeter())  # 输出: 30
# 尝试实例化抽象类会报错
# shape = Shape()  # TypeError: Can't instantiate abstract class Shape with abstract methods area, perimeter

2. 抽象属性

使用 @abstractmethod 可以定义抽象属性。

from abc import *
class Shape(ABC):
    @property
    @abstractmethod
    def name(self):
        pass
class Circle(Shape):
    @property
    def name(self):
        return "Circle"
circle = Circle()
print(circle.name)  # 输出: Circle

3. 抽象静态方法和类方法

可以使用 @abstractstaticmethod@abstractclassmethod

from abc import *
class Shape(ABC):
    @abstractstaticmethod
    def description():
        pass
    @abstractclassmethod
    def create(cls):
        pass
class Circle(Shape):
    @staticmethod
    def description():
        return "This is a Circle"
    @classmethod
    def create(cls):
        return cls()
circle = Circle()
print(Circle.description())  # 输出: This is a Circle
circle_instance = Circle.create()

4. 检查子类是否实现抽象方法

如果子类没有实现抽象方法,尝试实例化子类会抛出 TypeError

class IncompleteShape(Shape):
    pass
# 会报错,因为 IncompleteShape 没有实现 area 和 perimeter
# shape = IncompleteShape()  # TypeError: Can't instantiate abstract class IncompleteShape with abstract methods area, perimeter

5. abc 的高级用法

1. 注册虚拟子类

通过 register() 方法,可以将一个类注册为抽象基类的虚拟子类,而无需继承抽象基类。

from abc import ABC
class Shape(ABC):
    pass
class Polygon:
    def sides(self):
        return 4
# 将 Polygon 注册为 Shape 的虚拟子类
Shape.register(Polygon)
polygon = Polygon()
print(isinstance(polygon, Shape))  # 输出: True

注册虚拟子类的行为仅限于 isinstanceissubclass 检查,不会强制实现抽象方法。

2. 定义混入类

抽象基类可以作为混入类,提供公共方法供子类继承,同时要求子类实现特定方法。

from abc import ABC, abstractmethod
class JSONSerializable(ABC):
    @abstractmethod
    def to_json(self):
        pass
    def save(self, filepath):
        with open(filepath, 'w') as f:
            f.write(self.to_json())
class User(JSONSerializable):
    def __init__(self, name, age):
        self.name = name
        self.age = age
    def to_json(self):
        import json
        return json.dumps({"name": self.name, "age": self.age})
user = User("Alice", 30)
user.save("user.json")

 补充

方法解析顺序(MRO,Method Resolution Order)

方法解析顺序是 Python 中确定在类继承体系中调用方法时的查找顺序的规则。MRO 决定了在多继承场景下,当调用一个方法或属性时,Python 应该从哪个类开始查找,并以什么顺序继续查找。

一、MRO 的规则

  1. 深度优先、左到右
    Python 遵循一种称为 C3 线性化算法 的规则,该规则优先考虑深度优先,但会处理多继承中的冲突,确保类的继承关系是线性化的。

  2. 排除重复
    在继承树中,每个类只会被访问一次。

  3. 保持继承顺序一致
    子类的顺序会优先于父类,但父类的顺序会根据定义时的顺序进行保留。

二、查看 MRO

在 Python 中,可以使用以下方法查看一个类的 MRO:

  1. Class.mro() 方法:返回一个类的 MRO 列表。
  2. help(Class):显示类的信息,其中包含 MRO。

示例:

class A:
    def show(self):
        print("A")
class B(A):
    def show(self):
        print("B")
class C(A):
    pass
class D(B, C):
    pass
print(D.mro())
# 输出: [<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>]
help(D)

三、MRO 的应用场景

1. 多继承中方法冲突的处理

多继承时,如果多个父类有同名方法,MRO 会决定调用哪个父类的方法。

示例:

class A:
    def show(self):
        print("A")
class B(A):
    def show(self):
        print("B")
class C(A):
    def show(self):
        print("C")
class D(B, C):  # 多继承
    pass
d = D()
d.show()
# 输出: B
# MRO 确定 `D -> B -> C -> A -> object`

2. super() 的行为

super() 的调用遵循 MRO。当使用 super() 调用方法时,会按照 MRO 顺序继续查找下一个类的方法。

示例:

class A:
    def greet(self):
        print("Hello from A")
class B(A):
    def greet(self):
        print("Hello from B")
        super().greet()
class C(A):
    def greet(self):
        print("Hello from C")
        super().greet()
class D(B, C):
    def greet(self):
        print("Hello from D")
        super().greet()
d = D()
d.greet()
# 输出:
# Hello from D
# Hello from B
# Hello from C
# Hello from A

MRO 确保了 super() 按顺序调用各个父类的方法。

四、MRO 的规则解析(C3 线性化算法)

C3 线性化算法是一种合并算法,确保继承顺序具有一致性和逻辑性。

步骤

  1. 从子类到父类按顺序依次列出所有父类
  2. 确保子类优先于父类
  3. 如果一个类有多个父类,按定义顺序列出父类
  4. 保持父类中继承顺序的线性化

示例:

class A: pass
class B(A): pass
class C(A): pass
class D(B, C): pass
print(D.mro())
# 输出: [<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>]

五、特殊情况

1. 菱形继承问题

菱形继承是指某个子类从两个父类继承,而两个父类又共同继承自一个祖先类的情况。Python 的 MRO 通过 C3 线性化算法解决了菱形继承问题,避免重复调用祖先类的方法。

示例:

class A:
    def greet(self):
        print("Hello from A")
class B(A):
    def greet(self):
        print("Hello from B")
        super().greet()
class C(A):
    def greet(self):
        print("Hello from C")
        super().greet()
class D(B, C):
    pass
d = D()
d.greet()
# 输出:
# Hello from B
# Hello from C
# Hello from A

2. 无法线性化的继承关系

如果多继承中的顺序不符合 C3 线性化规则,Python 会报错。

示例:

class X: pass
class Y: pass
class A(X, Y): pass
class B(Y, X): pass
class C(A, B): pass  # 会报错,因为无法确定 MRO 顺序

到此这篇关于Python 继承详解(继承作用语法)的文章就介绍到这了,更多相关Python 继承内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Python常用特殊方法实例总结

    Python常用特殊方法实例总结

    这篇文章主要介绍了Python常用特殊方法,结合实例形式总结分析了Python常见的__init__、__new__、__del__、__str__、__repr__等特殊方法与描述符相关功能及使用技巧,需要的朋友可以参考下
    2019-03-03
  • Pandas读取并修改excel的示例代码

    Pandas读取并修改excel的示例代码

    这篇文章主要介绍了Pandas读取并修改excel的示例代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-02-02
  • 解决Python 出现File “<stdin>“, line 1非语法错误的问题

    解决Python 出现File “<stdin>“, line 1非语法错误的问题

    这篇文章主要介绍了Python 出现File “<stdin>“, line 1非语法错误的解决办法,本文给大家讲解的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-03-03
  • Python中函数的创建及调用

    Python中函数的创建及调用

    这篇文章主要介绍了Python中函数的创建及调用,创建函数也称为定义一个函数,可以理解为创建一个具有某种用途的工具。调用函数也就是执行函数。如果把创建的函数理解为创建一个具体有某种用途的工具,那么调用函数就相当于使用该工具
    2022-06-06
  • MacOS使用pyenv和brew优雅管理Python多版本环境

    MacOS使用pyenv和brew优雅管理Python多版本环境

    本文采用「pyenv + Homebrew」方案,为 MacOS 搭建干净、隔离的 Python 多版本环境,彻底避免污染系统自带 Python,完美适配不同项目版本需求,有需要的小伙伴可以参考下
    2026-03-03
  • 分享3个非常实用的 Python 模块

    分享3个非常实用的 Python 模块

    这篇文章主要爹大家分享的是分享3个非常实用的 Python 模块,知道的人可能不多,但是特别的好用,分别是Psutil、Pendulum、Pyfiglet三种模块,需要的小伙伴可以参考下面相关内容,希望对你有所帮助
    2022-03-03
  • 如何使用Python 抓取和优化所有网站图像

    如何使用Python 抓取和优化所有网站图像

    我发布了一个通过FTP自动优化新图像的教程。这次我们将抓取整个网站,并在本地优化我们遇到的图像,按URL组织,怎么来操作呢,下面跟随小编一起学习使用Python 抓取和优化所有网站图像的方法,感兴趣的朋友一起看看吧
    2023-02-02
  • Python调用ChatGPT的API实现文章生成

    Python调用ChatGPT的API实现文章生成

    最近ChatGPT大火,在3.5版本后开放了接口API,所以很多人开始进行实操,这里我就用python来为大家实现一下,如何调用API并提问返回文章的说明
    2023-03-03
  • Python matplotlib修改默认字体的操作

    Python matplotlib修改默认字体的操作

    这篇文章主要介绍了Python matplotlib修改默认字体的操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-03-03
  • 利用Python实现Markdown与Excel互转

    利用Python实现Markdown与Excel互转

    本文介绍了如何使用Python实现Excel和Markdown之间的转换,重点包括基础转换、高级设置调整、从复杂文档中提取表格并转换为Excel,转换原因包括提升文档兼容性、优化展示体验、适配版本控制、简化数据分析和工作流整合,文中提供了具体代码示例,帮助读者轻松实现转换
    2026-04-04

最新评论