11.Python 面向对象三大特性详解:封装、继承、多态与多继承、魔术方法及抽象类
摘要本文系统讲解了 Python 面向对象的三大特性——封装、继承重点涵盖多继承与 MRO和多态同时介绍了常用的魔术方法、魔术属性以及如何使用 abc 模块定义抽象类帮助开发者深入理解 Python 面向对象编程的核心机制与最佳实践。目录1. 封装数据与行为的捆绑1.1 私有属性和方法2. 继承复用与扩展2.1 单继承2.2 多继承2.3 方法解析顺序MRO3. 多态统一的接口不同的实现4. 魔术属性和魔术方法4.1 常用魔术方法4.2 常用魔术属性5. 抽象类定义接口规范1. 封装数据与行为的捆绑封装是面向对象编程的核心思想之一它将数据属性和操作数据的方法函数绑定在一起形成一个独立的单元——类。在 Python 中封装主要通过命名约定和访问控制来实现。1.1 私有属性和方法Python 没有严格的访问修饰符如 Java 的 private但社区约定以单下划线_name表示受保护的成员建议外部不要直接访问双下划线__name会触发名称改写机制使得外部难以直接访问从而实现更严格的私有化。class BankAccount: def __init__(self, owner, balance0): self.owner owner # 公开属性 self._balance balance # 受保护属性不建议外部直接修改 self.__password 1234 # 私有属性名称被改写为 _BankAccount__password def deposit(self, amount): if amount gt; 0: self._balance amount return self._balance def get_balance(self): return self._balance account BankAccount(Alice, 1000) print(account.get_balance()) # 1000 print(account.__password) # AttributeError print(account._BankAccount__password) # 仍可访问但不推荐封装的好处在于隐藏实现细节只暴露必要的接口提高代码的安全性和可维护性。2. 继承复用与扩展继承允许我们基于已有的类父类/基类创建新的类子类/派生类子类自动获得父类的属性和方法并可以添加或覆盖自己的行为。2.1 单继承class Animal: def __init__(self, name): self.name name def speak(self): return f{self.name} makes a sound. class Dog(Animal): def speak(self): # 方法重写 return f{self.name} barks. dog Dog(Buddy) print(dog.speak()) # Buddy barks.2.2 多继承Python 支持多继承即一个类可以同时继承多个父类。这使得代码复用更加灵活但也带来了方法解析顺序的复杂性。class Flyable: def fly(self): return I can fly! class Swimmable: def swim(self): return I can swim! class Duck(Animal, Flyable, Swimmable): def speak(self): return f{self.name} quacks. duck Duck(Donald) print(duck.speak()) # Donald quacks. (来自 Animal重写后) print(duck.fly()) # I can fly! (来自 Flyable) print(duck.swim()) # I can swim! (来自 Swimmable)2.3 方法解析顺序MRO当多个父类中存在同名方法时Python 使用 C3 线性化算法确定方法的搜索顺序。可以通过__mro__属性或mro()方法查看继承链。class A: def method(self): return A class B(A): def method(self): return B class C(A): def method(self): return C class D(B, C): pass print(D().method()) # B因为 MRO 为 D - B - C - A print(D.mro)多继承极大地增强了代码组合能力常与 Mixin 模式结合使用。Mixin 是一种只提供特定功能的类通常不单独实例化。class LoggerMixin: def log(self, message): print(f[LOG] {message}) class DataProcessor(LoggerMixin): def process(self, data): self.log(Processing data...) # 处理逻辑 return data processor DataProcessor() processor.process(sample)3. 多态统一的接口不同的实现多态指同一个接口可以根据对象类型的不同而表现出不同的行为。在 Python 中多态主要依赖鸭子类型只要对象实现了所需的方法就可以作为参数传递而不强制要求继承自特定基类。class Cat(Animal): def speak(self): return f{self.name} meows. class Bird(Animal): def speak(self): return f{self.name} chirps. def animal_sound(animal): print(animal.speak()) animal_sound(Dog(Rex)) # Rex barks. animal_sound(Cat(Whiskers)) # Whiskers meows. animal_sound(Bird(Tweety)) # Tweety chirps.多态让代码更加灵活、可扩展符合开闭原则。4. 魔术属性和魔术方法魔术方法Magic Methods是 Python 中以双下划线开头和结尾的特殊方法它们会在特定操作发生时被自动调用。魔术属性则是 Python 内置的特殊属性用于访问类的元信息。4.1 常用魔术方法__init__构造方法对象初始化时调用。__str__定义对象被str()或print()时的字符串表示。__repr__定义对象的官方字符串表示通常用于调试。__len__支持len()函数。__getitem__/__setitem__使对象支持下标访问。__call__使实例像函数一样可调用。__add__、__mul__等运算符重载。class Vector: def __init__(self, x, y): self.x x self.y y def __repr__(self): return fVector({self.x}, {self.y}) def add(self, other): return Vector(self.x other.x, self.y other.y) def len(self): return 2 v1 Vector(1, 2) v2 Vector(3, 4) print(v1 v2) # Vector(4, 6) print(len(v1)) # 24.2 常用魔术属性__dict__返回对象的属性字典。__class__返回对象所属的类。__doc__返回类的文档字符串。__name__返回类名字符串。__module__返回类定义所在的模块名。class Person: 人类模型 def __init__(self, name, age): self.name name self.age age p Person(Alice, 30) print(p.dict) # {name: Alice, age: 30} print(p.class) # class main.Person print(Person.doc) # 人类模型 print(Person.name) # Person5. 抽象类定义接口规范抽象类是一种不能直接实例化的类它定义了一组必须由子类实现的抽象方法。Python 通过abc模块提供抽象基类的支持。抽象类常与多态结合强制子类实现特定接口。from abc import ABC, abstractmethod class Shape(ABC): abstractmethod def area(self): pass abstractmethod def perimeter(self): pass class Circle(Shape): def init(self, radius): self.radius radius def area(self): return 3.14159 * self.radius ** 2 def perimeter(self): return 2 * 3.14159 * self.radius 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) shapes [Circle(5), Rectangle(4, 6)] for s in shapes: print(f{s.class.name} area: {s.area()}) Circle area: 78.53975 Rectangle area: 24抽象类确保了所有子类都遵循统一的接口约定提高了代码的健壮性和可读性。如果子类未实现所有抽象方法Python 会在实例化时抛出TypeError。