Python面向对象编程深度解析:类与对象、继承与多态实战指南

面向对象编程(OOP)是现代编程语言的基石,Python作为一门多范式语言,其面向对象特性既强大又灵活。然而很多开发者在类设计、继承关系和多态应用上存在困惑。本文将深入解析Python面向对象编程的核心概念,帮助你构建更优雅、可维护的代码结构。

图片[1]-Python面向对象编程深度解析:类与对象、继承与多态实战指南

一、类与对象:从基础到高级

1. 类的基本结构与实例化

基础类定义

class Student:
    """学生类示例"""
    
    # 类属性 - 所有实例共享
    school = "阳光中学"
    
    def __init__(self, name, age, grade):
        """初始化方法 - 构造器"""
        # 实例属性 - 每个实例独有
        self.name = name
        self.age = age
        self.grade = grade
        self._score = 0  # 受保护的属性
        self.__id = self._generate_id()  # 私有属性
    
    def _generate_id(self):
        """生成学生ID(受保护方法)"""
        import random
        return f"STU{random.randint(1000, 9999)}"
    
    def study(self, subject, hours=1):
        """学习方法"""
        print(f"{self.name} 正在学习 {subject},时长 {hours} 小时")
        self._score += hours * 0.5  # 学习增加分数
        return self._score
    
    def get_score(self):
        """获取分数"""
        return self._score
    
    def __str__(self):
        """字符串表示"""
        return f"学生: {self.name}, 年龄: {self.age}, 年级: {self.grade}"
    
    def __repr__(self):
        """解释器表示"""
        return f"Student('{self.name}', {self.age}, '{self.grade}')"

# 创建对象实例
student1 = Student("张三", 15, "高一")
student2 = Student("李四", 16, "高二")

print(student1)  # 学生: 张三, 年龄: 15, 年级: 高一
print(student2)  # 学生: 李四, 年龄: 16, 年级: 高二

# 调用方法
student1.study("数学", 2)
print(f"{student1.name}的分数: {student1.get_score()}")  # 张三的分数: 1.0

# 访问属性
print(f"学校: {Student.school}")  # 学校: 阳光中学
print(f"{student1.name}在{student1.school}上学")

2. 属性访问控制与封装

封装实践

class BankAccount:
    """银行账户类 - 封装示例"""
    
    def __init__(self, account_holder, initial_balance=0):
        self.account_holder = account_holder
        self._balance = initial_balance  # 受保护属性
        self.__account_number = self._generate_account_number()  # 私有属性
        self._transaction_history = []
    
    def _generate_account_number(self):
        """生成账户号码(内部方法)"""
        import random
        return f"ACC{random.randint(100000, 999999)}"
    
    def deposit(self, amount):
        """存款"""
        if amount > 0:
            self._balance += amount
            self._transaction_history.append(f"存款: +{amount}")
            print(f"成功存款 {amount}元")
            return True
        else:
            print("存款金额必须大于0")
            return False
    
    def withdraw(self, amount):
        """取款"""
        if 0 < amount <= self._balance:
            self._balance -= amount
            self._transaction_history.append(f"取款: -{amount}")
            print(f"成功取款 {amount}元")
            return True
        else:
            print("取款失败:余额不足或金额无效")
            return False
    
    def get_balance(self):
        """获取余额(公共接口)"""
        return self._balance
    
    def get_transaction_history(self):
        """获取交易记录(只读)"""
        return self._transaction_history.copy()  # 返回副本,保护原始数据
    
    # 使用property装饰器创建计算属性
    @property
    def account_info(self):
        """账户信息(只读属性)"""
        return {
            "holder": self.account_holder,
            "balance": self._balance,
            "account_number": self.__account_number
        }
    
    # 静态方法 - 不依赖实例
    @staticmethod
    def validate_amount(amount):
        """验证金额是否有效"""
        return isinstance(amount, (int, float)) and amount > 0
    
    # 类方法 - 操作类属性
    @classmethod
    def get_bank_name(cls):
        return "Python银行"

# 使用示例
account = BankAccount("王五", 1000)
print(f"银行名称: {BankAccount.get_bank_name()}")

account.deposit(500)
account.withdraw(200)
print(f"当前余额: {account.get_balance()}元")  # 1300

# 通过property访问
print(f"账户信息: {account.account_info}")

# 验证封装
try:
    print(account.__account_number)  # 报错:AttributeError
except AttributeError as e:
    print(f"无法直接访问私有属性: {e}")

# 但Python的私有属性实际上是名称修饰
print(account._BankAccount__account_number)  # 可以访问,但不推荐

二、继承与多态深度解析

1. 基础继承与方法重写

class Animal:
    """动物基类"""
    
    def __init__(self, name, age):
        self.name = name
        self.age = age
        self._energy = 100
    
    def eat(self):
        """吃东西"""
        self._energy += 20
        print(f"{self.name} 正在吃东西")
    
    def sleep(self):
        """睡觉"""
        self._energy += 50
        print(f"{self.name} 正在睡觉")
    
    def make_sound(self):
        """发出声音(抽象方法,子类必须实现)"""
        raise NotImplementedError("子类必须实现make_sound方法")
    
    def get_energy(self):
        return self._energy
    
    def __str__(self):
        return f"{self.__class__.__name__}: {self.name}, 年龄: {self.age}"

class Dog(Animal):
    """狗类 - 继承自动物"""
    
    def __init__(self, name, age, breed):
        super().__init__(name, age)  # 调用父类初始化
        self.breed = breed  # 子类特有属性
    
    def make_sound(self):
        """重写父类方法"""
        return "汪汪!"
    
    def fetch(self):
        """子类特有方法"""
        if self._energy >= 10:
            self._energy -= 10
            print(f"{self.name} 正在接飞盘")
            return True
        else:
            print(f"{self.name} 太累了,需要休息")
            return False
    
    def __str__(self):
        """重写字符串表示"""
        return f"{super().__str__()}, 品种: {self.breed}"

class Cat(Animal):
    """猫类 - 继承自动物"""
    
    def __init__(self, name, age, color):
        super().__init__(name, age)
        self.color = color
    
    def make_sound(self):
        """重写父类方法"""
        return "喵喵!"
    
    def climb_tree(self):
        """子类特有方法"""
        if self._energy >= 15:
            self._energy -= 15
            print(f"{self.name} 正在爬树")
            return True
        else:
            print(f"{self.name} 太累了,需要休息")
            return False

# 多态演示
def animal_concert(animals):
    """动物音乐会 - 多态示例"""
    for animal in animals:
        print(f"{animal.name} 说: {animal.make_sound()}")

# 创建不同动物实例
dog = Dog("旺财", 3, "金毛")
cat = Cat("咪咪", 2, "白色")

print(dog)  # Dog: 旺财, 年龄: 3, 品种: 金毛
print(cat)  # Cat: 咪咪, 年龄: 2

# 多态调用
animals = [dog, cat]
animal_concert(animals)
# 输出:
# 旺财 说: 汪汪!
# 咪咪 说: 喵喵!

# 调用各自特有方法
dog.fetch()
cat.climb_tree()

print(f"{dog.name}的能量: {dog.get_energy()}")
print(f"{cat.name}的能量: {cat.get_energy()}")

2. 多重继承与方法解析顺序(MRO)

class Flyable:
    """可飞行能力"""
    
    def __init__(self, max_altitude=1000):
        self.max_altitude = max_altitude
        self._is_flying = False
    
    def take_off(self):
        """起飞"""
        if not self._is_flying:
            self._is_flying = True
            print("起飞!")
        return self._is_flying
    
    def land(self):
        """降落"""
        if self._is_flying:
            self._is_flying = False
            print("降落!")
        return not self._is_flying
    
    def fly(self):
        """飞行"""
        if self._is_flying:
            print(f"正在飞行,最高海拔: {self.max_altitude}米")
            return True
        else:
            print("请先起飞")
            return False

class Swimmable:
    """可游泳能力"""
    
    def __init__(self, max_depth=10):
        self.max_depth = max_depth
        self._is_swimming = False
    
    def dive(self):
        """潜水"""
        if not self._is_swimming:
            self._is_swimming = True
            print("潜入水中!")
        return self._is_swimming
    
    def surface(self):
        """浮出水面"""
        if self._is_swimming:
            self._is_swimming = False
            print("浮出水面!")
        return not self._is_swimming
    
    def swim(self):
        """游泳"""
        if self._is_swimming:
            print(f"正在游泳,最大深度: {self.max_depth}米")
            return True
        else:
            print("请先潜水")
            return False

class Duck(Animal, Flyable, Swimmable):
    """鸭子 - 多重继承"""
    
    def __init__(self, name, age):
        # 初始化所有父类
        Animal.__init__(self, name, age)
        Flyable.__init__(self, max_altitude=500)  # 鸭子飞不高
        Swimmable.__init__(self, max_depth=5)     # 鸭子潜不深
    
    def make_sound(self):
        return "嘎嘎!"
    
    def daily_routine(self):
        """鸭子日常 - 展示多重继承的能力"""
        print(f"\n=== {self.name}的日常 ===")
        self.eat()
        self.take_off()
        self.fly()
        self.land()
        self.dive()
        self.swim()
        self.surface()
        self.sleep()

# 查看方法解析顺序
print("Duck类的MRO:", Duck.__mro__)

# 使用多重继承的类
duck = Duck("唐老鸭", 2)
print(duck.make_sound())  # 嘎嘎!

duck.daily_routine()
# 输出:
# === 唐老鸭的日常 ===
# 唐老鸭 正在吃东西
# 起飞!
# 正在飞行,最高海拔: 500米
# 降落!
# 潜入水中!
# 正在游泳,最大深度: 5米
# 浮出水面!
# 唐老鸭 正在睡觉

3. 抽象基类(ABC)与接口设计

from abc import ABC, abstractmethod
from typing import List

class Shape(ABC):
    """形状抽象基类"""
    
    @abstractmethod
    def area(self) -> float:
        """计算面积"""
        pass
    
    @abstractmethod
    def perimeter(self) -> float:
        """计算周长"""
        pass
    
    @abstractmethod
    def draw(self) -> None:
        """绘制形状"""
        pass
    
    # 具体方法 - 子类共享
    def describe(self) -> str:
        """描述形状"""
        return f"{self.__class__.__name__}: 面积={self.area():.2f}, 周长={self.perimeter():.2f}"

class Rectangle(Shape):
    """矩形类"""
    
    def __init__(self, width: float, height: float):
        self.width = width
        self.height = height
    
    def area(self) -> float:
        return self.width * self.height
    
    def perimeter(self) -> float:
        return 2 * (self.width + self.height)
    
    def draw(self) -> None:
        print(f"绘制矩形: {self.width}×{self.height}")

class Circle(Shape):
    """圆形类"""
    
    def __init__(self, radius: float):
        self.radius = radius
    
    def area(self) -> float:
        import math
        return math.pi * self.radius ** 2
    
    def perimeter(self) -> float:
        import math
        return 2 * math.pi * self.radius
    
    def draw(self) -> None:
        print(f"绘制圆形: 半径={self.radius}")

class Triangle(Shape):
    """三角形类"""
    
    def __init__(self, a: float, b: float, c: float):
        self.a = a
        self.b = b
        self.c = c
    
    def area(self) -> float:
        # 使用海伦公式
        s = self.perimeter() / 2
        import math
        return math.sqrt(s * (s - self.a) * (s - self.b) * (s - self.c))
    
    def perimeter(self) -> float:
        return self.a + self.b + self.c
    
    def draw(self) -> None:
        print(f"绘制三角形: 边长={self.a},{self.b},{self.c}")

def process_shapes(shapes: List[Shape]) -> None:
    """处理形状集合 - 多态应用"""
    total_area = 0
    total_perimeter = 0
    
    for shape in shapes:
        shape.draw()
        print(shape.describe())
        total_area += shape.area()
        total_perimeter += shape.perimeter()
        print("-" * 30)
    
    print(f"总面积: {total_area:.2f}")
    print(f"总周长: {total_perimeter:.2f}")

# 使用抽象基类
shapes = [
    Rectangle(5, 3),
    Circle(4),
    Triangle(3, 4, 5)
]

process_shapes(shapes)

# 尝试实例化抽象类会报错
try:
    shape = Shape()  # TypeError: Can't instantiate abstract class Shape
except TypeError as e:
    print(f"错误: {e}")

三、魔术方法与运算符重载

1. 常用魔术方法实践

class Vector:
    """向量类 - 魔术方法示例"""
    
    def __init__(self, x=0, y=0, z=0):
        self.x = x
        self.y = y
        self.z = z
    
    # 表示方法
    def __str__(self):
        return f"Vector({self.x}, {self.y}, {self.z})"
    
    def __repr__(self):
        return f"Vector({self.x}, {self.y}, {self.z})"
    
    # 比较运算符
    def __eq__(self, other):
        if not isinstance(other, Vector):
            return False
        return self.x == other.x and self.y == other.y and self.z == other.z
    
    def __lt__(self, other):
        """比较向量长度"""
        return self.magnitude() < other.magnitude()
    
    # 数学运算符
    def __add__(self, other):
        """向量加法"""
        if isinstance(other, Vector):
            return Vector(self.x + other.x, self.y + other.y, self.z + other.z)
        return NotImplemented
    
    def __sub__(self, other):
        """向量减法"""
        if isinstance(other, Vector):
            return Vector(self.x - other.x, self.y - other.y, self.z - other.z)
        return NotImplemented
    
    def __mul__(self, other):
        """向量乘法(数乘或点乘)"""
        if isinstance(other, (int, float)):
            return Vector(self.x * other, self.y * other, self.z * other)
        elif isinstance(other, Vector):
            # 点乘
            return self.x * other.x + self.y * other.y + self.z * other.z
        return NotImplemented
    
    def __rmul__(self, other):
        """右乘法"""
        return self.__mul__(other)
    
    # 其他魔术方法
    def __getitem__(self, index):
        """支持索引访问"""
        if index == 0:
            return self.x
        elif index == 1:
            return self.y
        elif index == 2:
            return self.z
        else:
            raise IndexError("Vector index out of range")
    
    def __setitem__(self, index, value):
        """支持索引赋值"""
        if index == 0:
            self.x = value
        elif index == 1:
            self.y = value
        elif index == 2:
            self.z = value
        else:
            raise IndexError("Vector index out of range")
    
    def __len__(self):
        """向量维度"""
        return 3
    
    def __bool__(self):
        """布尔值:零向量为False"""
        return self.x != 0 or self.y != 0 or self.z != 0
    
    def __contains__(self, value):
        """检查值是否存在"""
        return value in (self.x, self.y, self.z)
    
    # 普通方法
    def magnitude(self):
        """向量长度"""
        import math
        return math.sqrt(self.x**2 + self.y**2 + self.z**2)
    
    def dot(self, other):
        """点乘"""
        return self.__mul__(other)
    
    def cross(self, other):
        """叉乘"""
        return Vector(
            self.y * other.z - self.z * other.y,
            self.z * other.x - self.x * other.z,
            self.x * other.y - self.y * other.x
        )

# 测试魔术方法
v1 = Vector(1, 2, 3)
v2 = Vector(4, 5, 6)

print(f"v1 = {v1}")  # Vector(1, 2, 3)
print(f"v2 = {v2}")  # Vector(4, 5, 6)

# 运算符重载
print(f"v1 + v2 = {v1 + v2}")  # Vector(5, 7, 9)
print(f"v1 - v2 = {v1 - v2}")  # Vector(-3, -3, -3)
print(f"v1 * 2 = {v1 * 2}")    # Vector(2, 4, 6)
print(f"2 * v1 = {2 * v1}")    # Vector(2, 4, 6)
print(f"v1 · v2 = {v1 * v2}")  # 32 (点乘)

# 比较运算
print(f"v1 == v2: {v1 == v2}")  # False
print(f"v1 < v2: {v1 < v2}")    # 比较长度

# 索引访问
print(f"v1[0] = {v1[0]}")  # 1
v1[1] = 10
print(f"修改后 v1 = {v1}")  # Vector(1, 10, 3)

# 其他魔术方法
print(f"向量长度: {len(v1)}")          # 3
print(f"向量是否非零: {bool(v1)}")     # True
print(f"值2是否在向量中: {2 in v1}")   # False (因为修改了y为10)

2. 上下文管理器魔术方法

class DatabaseConnection:
    """数据库连接 - 上下文管理器示例"""
    
    def __init__(self, database_url):
        self.database_url = database_url
        self.connection = None
        self.transaction_count = 0
    
    def __enter__(self):
        """进入上下文时调用"""
        print(f"连接到数据库: {self.database_url}")
        self.connection = self._create_connection()
        return self
    
    def __exit__(self, exc_type, exc_val, exc_tb):
        """退出上下文时调用"""
        if self.connection:
            if exc_type is None:
                print("提交事务并关闭连接")
                self.connection.commit()
            else:
                print(f"发生错误,回滚事务: {exc_val}")
                self.connection.rollback()
            
            self.connection.close()
            print("数据库连接已关闭")
        
        # 返回False让异常继续传播,True则抑制异常
        return False
    
    def _create_connection(self):
        """模拟创建数据库连接"""
        class MockConnection:
            def commit(self):
                print("事务提交")
            
            def rollback(self):
                print("事务回滚")
            
            def close(self):
                print("连接关闭")
        
        return MockConnection()
    
    def execute_query(self, query):
        """执行查询"""
        print(f"执行查询: {query}")
        self.transaction_count += 1
        return f"结果{self.transaction_count}"

# 使用上下文管理器
print("=== 正常执行 ===")
with DatabaseConnection("mysql://localhost:3306/mydb") as db:
    result1 = db.execute_query("SELECT * FROM users")
    result2 = db.execute_query("UPDATE products SET price = 100")
    print(f"查询结果: {result1}, {result2}")

print("\n=== 发生异常的情况 ===")
try:
    with DatabaseConnection("mysql://localhost:3306/mydb") as db:
        db.execute_query("SELECT * FROM users")
        raise ValueError("模拟数据库错误")
        db.execute_query("UPDATE products")  # 这行不会执行
except ValueError as e:
    print(f"捕获到异常: {e}")

四、高级类特性与元编程

1. 描述符(Descriptor)高级应用

class ValidatedAttribute:
    """验证描述符"""
    
    def __init__(self, min_value=None, max_value=None, allowed_types=None):
        self.min_value = min_value
        self.max_value = max_value
        self.allowed_types = allowed_types
        self.name = None  # 将在__set_name__中设置
    
    def __set_name__(self, owner, name):
        self.name = name
    
    def __get__(self, instance, owner):
        if instance is None:
            return self
        return instance.__dict__.get(self.name)
    
    def __set__(self, instance, value):
        self._validate(value)
        instance.__dict__[self.name] = value
    
    def _validate(self, value):
        """验证属性值"""
        if self.allowed_types and not isinstance(value, self.allowed_types):
            raise TypeError(f"{self.name} 必须是 {self.allowed_types} 类型")
        
        if self.min_value is not None and value < self.min_value:
            raise ValueError(f"{self.name} 不能小于 {self.min_value}")
        
        if self.max_value is not None and value > self.max_value:
            raise ValueError(f"{self.name} 不能大于 {self.max_value}")

class Person:
    """使用描述符的Person类"""
    
    # 使用描述符定义属性
    age = ValidatedAttribute(min_value=0, max_value=150, allowed_types=(int,))
    height = ValidatedAttribute(min_value=0.0, max_value=3.0, allowed_types=(int, float))
    name = ValidatedAttribute(allowed_types=(str,))
    
    def __init__(self, name, age, height):
        self.name = name
        self.age = age
        self.height = height
    
    def __str__(self):
        return f"Person(name={self.name}, age={self.age}, height={self.height})"

# 测试描述符
try:
    person = Person("Alice", 25, 1.65)
    print(person)  # Person(name=Alice, age=25, height=1.65)
    
    # 测试验证
    person.age = 30  # 正常
    print(f"修改后年龄: {person.age}")
    
    person.age = -5  # 报错: ValueError
except ValueError as e:
    print(f"验证错误: {e}")

try:
    person.name = 123  # 报错: TypeError
except TypeError as e:
    print(f"类型错误: {e}")

2. 元类基础

class SingletonMeta(type):
    """单例元类"""
    
    _instances = {}
    
    def __call__(cls, *args, **kwargs):
        if cls not in cls._instances:
            cls._instances[cls] = super().__call__(*args, **kwargs)
        return cls._instances[cls]

class AutoRegisterMeta(type):
    """自动注册元类"""
    
    def __init__(cls, name, bases, attrs):
        super().__init__(name, bases, attrs)
        if not hasattr(cls, '_registry'):
            cls._registry = {}
        else:
            # 注册子类
            cls._registry[name] = cls

class DatabaseManager(metaclass=SingletonMeta):
    """单例数据库管理器"""
    
    def __init__(self):
        self.connections = {}
        print("数据库管理器初始化")
    
    def connect(self, database_name):
        if database_name not in self.connections:
            self.connections[database_name] = f"连接_{database_name}"
            print(f"创建到 {database_name} 的连接")
        return self.connections[database_name]

class PluginBase(metaclass=AutoRegisterMeta):
    """插件基类"""
    pass

class EmailPlugin(PluginBase):
    """邮件插件"""
    pass

class AuthPlugin(PluginBase):
    """认证插件"""
    pass

# 测试单例
print("=== 单例模式测试 ===")
db1 = DatabaseManager()
db2 = DatabaseManager()

print(f"db1 is db2: {db1 is db2}")  # True

db1.connect("users")
db2.connect("products")  # 使用的是同一个实例

# 测试自动注册
print("\n=== 自动注册测试 ===")
print("注册的插件类:", PluginBase._registry)
# 输出: {'EmailPlugin': <class '__main__.EmailPlugin'>, 'AuthPlugin': <class '__main__.AuthPlugin'>}

五、设计模式在Python中的实现

1. 工厂模式

from enum import Enum

class NotificationType(Enum):
    EMAIL = "email"
    SMS = "sms"
    PUSH = "push"

class Notification:
    """通知基类"""
    
    def send(self, message: str) -> bool:
        raise NotImplementedError

class EmailNotification(Notification):
    def send(self, message: str) -> bool:
        print(f"发送邮件通知: {message}")
        return True

class SMSNotification(Notification):
    def send(self, message: str) -> bool:
        print(f"发送短信通知: {message}")
        return True

class PushNotification(Notification):
    def send(self, message: str) -> bool:
        print(f"发送推送通知: {message}")
        return True

class NotificationFactory:
    """通知工厂"""
    
    @staticmethod
    def create_notification(notification_type: NotificationType) -> Notification:
        creators = {
            NotificationType.EMAIL: EmailNotification,
            NotificationType.SMS: SMSNotification,
            NotificationType.PUSH: PushNotification,
        }
        
        creator = creators.get(notification_type)
        if not creator:
            raise ValueError(f"不支持的通知类型: {notification_type}")
        
        return creator()

# 使用工厂
factory = NotificationFactory()

notifications = [
    factory.create_notification(NotificationType.EMAIL),
    factory.create_notification(NotificationType.SMS),
    factory.create_notification(NotificationType.PUSH),
]

for notification in notifications:
    notification.send("系统通知消息")

2. 观察者模式

from abc import ABC, abstractmethod
from typing import List

class Observer(ABC):
    """观察者接口"""
    
    @abstractmethod
    def update(self, subject: 'Subject') -> None:
        pass

class Subject(ABC):
    """主题接口"""
    
    def __init__(self):
        self._observers: List[Observer] = []
    
    def attach(self, observer: Observer) -> None:
        if observer not in self._observers:
            self._observers.append(observer)
    
    def detach(self, observer: Observer) -> None:
        self._observers.remove(observer)
    
    def notify(self) -> None:
        for observer in self._observers:
            observer.update(self)

class WeatherStation(Subject):
    """气象站 - 具体主题"""
    
    def __init__(self):
        super().__init__()
        self._temperature = 0
        self._humidity = 0
        self._pressure = 0
    
    @property
    def temperature(self):
        return self._temperature
    
    @property
    def humidity(self):
        return self._humidity
    
    @property
    def pressure(self):
        return self._pressure
    
    def set_measurements(self, temperature: float, humidity: float, pressure: float) -> None:
        self._temperature = temperature
        self._humidity = humidity
        self._pressure = pressure
        self.notify()  # 通知所有观察者

class DisplayDevice(Observer):
    """显示设备 - 具体观察者"""
    
    def __init__(self, name: str):
        self.name = name
    
    def update(self, subject: Subject) -> None:
        if isinstance(subject, WeatherStation):
            print(f"[{self.name}] 温度: {subject.temperature}°C, "
                  f"湿度: {subject.humidity}%, 气压: {subject.pressure}hPa")

# 使用观察者模式
weather_station = WeatherStation()

# 创建多个显示设备
phone_display = DisplayDevice("手机")
tv_display = DisplayDevice("电视")
tablet_display = DisplayDevice("平板")

# 注册观察者
weather_station.attach(phone_display)
weather_station.attach(tv_display)
weather_station.attach(tablet_display)

# 更新气象数据,自动通知所有观察者
print("=== 第一次更新 ===")
weather_station.set_measurements(25.5, 65, 1013.2)

print("\n=== 第二次更新(移除一个观察者)===")
weather_station.detach(tv_display)
weather_station.set_measurements(26.0, 63, 1012.8)

六、调试与最佳实践

1. 类调试工具

import inspect

def analyze_class(cls):
    """分析类的结构"""
    print(f"=== 分析类: {cls.__name__} ===")
    
    # 获取类的方法和属性
    methods = []
    attributes = []
    
    for name, member in inspect.getmembers(cls):
        if name.startswith('__') and name.endswith('__'):
            continue
        
        if inspect.ismethod(member) or inspect.isfunction(member):
            methods.append(name)
        else:
            attributes.append(name)
    
    print(f"方法: {methods}")
    print(f"属性: {attributes}")
    
    # 获取MRO
    print(f"方法解析顺序: {cls.__mro__}")
    
    # 检查是否为抽象类
    if hasattr(cls, '__abstractmethods__') and cls.__abstractmethods__:
        print(f"抽象方法: {cls.__abstractmethods__}")

# 分析之前定义的类
analyze_class(Student)
analyze_class(Shape)

2. 面向对象设计原则

"""
面向对象设计原则(SOLID)在Python中的体现:

1. 单一职责原则 (SRP)
   - 每个类只负责一个功能领域
   - 示例:DatabaseConnection只负责数据库连接,Notification只负责通知

2. 开闭原则 (OCP)
   - 对扩展开放,对修改关闭
   - 示例:使用抽象基类Shape,可以轻松添加新的形状

3. 里氏替换原则 (LSP)
   - 子类应该可以替换父类
   - 示例:Dog和Cat可以替换Animal

4. 接口隔离原则 (ISP)
   - 使用多个专门的接口而不是一个通用接口
   - 示例:Flyable和Swimmable分离飞行和游泳能力

5. 依赖倒置原则 (DIP)
   - 依赖抽象而不是具体实现
   - 示例:process_shapes依赖Shape抽象而不是具体形状类
"""

class SOLIDExample:
    """SOLID原则示例"""
    
    # 单一职责:这个类只负责用户验证
    @staticmethod
    def validate_user(username, email, age):
        errors = []
        if len(username) < 3:
            errors.append("用户名至少3个字符")
        if '@' not in email:
            errors.append("邮箱格式不正确")
        if age < 0 or age > 150:
            errors.append("年龄无效")
        return errors

# 使用示例
errors = SOLIDExample.validate_user("ab", "invalid-email", 200)
if errors:
    print("验证错误:", errors)
else:
    print("验证通过")

总结

Python面向对象编程提供了强大而灵活的工具来构建复杂的应用程序。关键要点总结:

  1. 类设计:合理使用封装,通过property控制属性访问
  2. 继承体系:理解MRO,善用抽象基类定义接口契约
  3. 多态应用:利用鸭子类型,编写通用的处理函数
  4. 魔术方法:通过运算符重载让自定义类更Pythonic
  5. 高级特性:掌握描述符、元类等元编程技术
  6. 设计模式:在Python中优雅实现常见设计模式

面向对象编程不仅仅是语法,更是一种思维方式。通过合理运用这些概念,你可以构建出更可维护、可扩展的Python应用程序。

© 版权声明
THE END
喜欢就支持一下吧
点赞10 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容