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

作者:

文章目录
  • 代码复用子类继承父类的属性和方法,无需重复编写相同代码。 逻辑层次清晰通过继承关系表达对象间的从属关系,使代码更具结构性。 增强扩展性子类可以在继承父类的基础上扩展新的属性或方法,支持功能扩展。 多态性子类可以重写父类的方法,实现不同的行为。
  • 在 Python 中,继承通过类定义时括号中的父类名实现。
  • 子类可以添加新的属性和方法,或者重写父类的方法。
  • 通过继承实现抽象类和接口功能。
  • 目录
    •  补充
      • 方法解析顺序(MRO,Method Resolution Order)
      • 一、MRO 的规则
      • 二、查看 MRO
      • 三、MRO 的应用场景
        • 1. 多继承中方法冲突的处理
        • 2. super() 的行为
      • 四、MRO 的规则解析(C3 线性化算法)
        • 步骤
      • 五、特殊情况
        • 1. 菱形继承问题
        • 2. 无法线性化的继承关系

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

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

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

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

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

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

    子类继承单个父类:

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

    子类继承多个父类:

    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) 查看。

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

    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

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

    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

    使用 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

    如果父类有 __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

    多继承时,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

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

    使用 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

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

    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

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

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

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

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

    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

    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")

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

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

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

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

    在 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 会决定调用哪个父类的方法。

    示例:

    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`

    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() 按顺序调用各个父类的方法。

    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'>]

    菱形继承是指某个子类从两个父类继承,而两个父类又共同继承自一个祖先类的情况。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

    如果多继承中的顺序不符合 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语法学习之super(),继承与派生
    • Python进阶语法之类的继承
    • python中的继承机制super()函数详解
    • 详解Python3中的多重继承和混入类
    • Python入门教程(二十三)Python的继承
    • python子类在多继承中使用MRO机制原理

    站内搜索