Python面向对象编程

一、面向对象编程核心概念体系

1.1 OOP四大支柱与实现要素

抽象
类Class
封装
访问控制
继承
代码复用
多态
接口统一
成员变量
成员方法
self机制
私有变量
属性装饰器

1.2 开发思维对比

过程式编程面向对象编程
关注"怎么做"关注"谁来做"
函数操作数据数据与行为结合
适合线性流程适合复杂系统
数据全局可见数据受对象保护

二、类与对象深度解析

2.1 类定义标准模板

class MobilePhone:
    """移动设备抽象类
    
    Attributes:
        brand: 品牌名称(实例属性)
        _imei: 设备唯一标识(私有属性)
        os_type: 操作系统类型(类属性)
    """
    
    os_type = "Android"  # 类属性
    
    def __init__(self, brand: str, imei: str):
        """初始化设备信息
        
        Args:
            brand: 品牌名称(长度2-20字符)
            imei: 国际移动设备识别码(15位数字)
        """
        if not (2 <= len(brand) <= 20):
            raise ValueError("品牌名称长度无效")
        if len(imei) != 15 or not imei.isdigit():
            raise ValueError("IMEI格式错误")
            
        self.brand = brand        # 实例属性
        self._imei = imei         # 私有属性
        self.__secret_code = ""   # 名称改编私有属性
    
    def verify_imei(self, input_imei: str) -> bool:
        """验证IMEI码(通过self访问私有属性)"""
        return self._imei == input_imei
    
    @classmethod
    def change_os(cls, new_os: str):
        """修改类属性"""
        cls.os_type = new_os

2.2 对象实例化过程解析

# 类调用过程
my_phone = MobilePhone("HUAWEI", "123456789012345")

'''
内存变化过程:
1. 调用__new__方法分配内存空间
2. __init__方法通过self参数初始化对象:
   - self.brand = "HUAWEI" 
   - self._imei = "123456789012345"
3. 返回对象引用给my_phone变量
'''

三、构造方法(__inint__

3.1 构造方法的核心作用

class Employee:
    def __init__(self, name: str, emp_id: str, department: str):
        """构造方法三要素:
        1. 初始化实例属性
        2. 参数验证
        3. 建立对象初始状态
        """
        # 参数验证
        if len(emp_id) != 6 or not emp_id.isdigit():
            raise ValueError("员工ID必须为6位数字")
        
        # 属性初始化
        self.name = name
        self.emp_id = emp_id
        self.department = department
        self._salary = 0.0  # 私有属性
        
        # 初始化关联对象
        self.access_card = AccessCard(emp_id)  # 组合关系

class AccessCard:
    def __init__(self, card_id: str):
        self.card_id = card_id
        self.activated = False

3.2 构造方法执行流程

__new__方法__init__方法对象调用__new__分配内存创建空对象自动调用__init__初始化对象状态返回初始化后的对象__new__方法__init__方法对象

3.3 构造方法六大特性

特性1:强制命名规范
class CorrectClass:
    def __init__(self):  # ✅ 正确命名
        pass

class ErrorClass:
    def initialize(self):  # ❌ 不会被自动调用
        pass
特性2:可选的返回值
class ReturnTest:
    def __init__(self):
        return None  # ✅ 允许返回None(默认行为)
    
    # def __init__(self):  # ❌ 返回非None值会报错
    #     return 123
特性3:继承链调用
class Animal:
    def __init__(self, species: str):
        self.species = species
        print(f"Animal初始化: {species}")

class Dog(Animal):
    def __init__(self, name: str, breed: str):
        super().__init__("犬科")  # ✅ 显式调用父类构造
        self.name = name
        self.breed = breed
        print(f"Dog初始化: {name}")

# 实例化过程输出:
# Animal初始化: 犬科
# Dog初始化: 旺财
特性4:支持默认参数
class NetworkConfig:
    def __init__(self, 
                 ip: str = "192.168.1.1",
                 port: int = 8080):
        self.ip = ip
        self.port = port

# 使用示例
default_config = NetworkConfig()
custom_config = NetworkConfig("10.0.0.1", 9000)
特性5:参数验证
class TemperatureSensor:
    def __init__(self, current_temp: float):
        if not (-273.15 <= current_temp <= 1000):
            raise ValueError("温度值超出物理可能范围")
        self.temperature = current_temp
        self._unit = "℃"
特性6:复合初始化
class Computer:
    def __init__(self, cpu_model: str):
        self.cpu = cpu_model
        self._init_peripherals()  # 调用初始化方法
        
    def _init_peripherals(self):
        """初始化外设默认状态"""
        self.keyboard = "USB键盘"
        self.mouse = "无线鼠标"
        self.display = "4K显示器"

3.2构造方法设计模式

3.2.1 工厂模式
class Document:
    def __init__(self, doc_type: str, content: str):
        self.type = doc_type
        self.content = content
    
    @classmethod
    def from_file(cls, file_path: str):
        """替代构造方法:从文件创建"""
        with open(file_path, 'r') as f:
            content = f.read()
        return cls(
            doc_type=file_path.split('.')[-1],
            content=content
        )

# 使用示例
doc1 = Document("txt", "Hello World")
doc2 = Document.from_file("report.docx")
3.2.2 建造者模式
class CarBuilder:
    def __init__(self):
        self.car = Car()
    
    def set_engine(self, engine: str):
        self.car.engine = engine
        return self
    
    def set_wheels(self, count: int):
        self.car.wheels = count
        return self
    
    def build(self):
        return self.car

class Car:
    def __init__(self):
        self.engine = None
        self.wheels = 0

# 使用示例
builder = CarBuilder()
car = builder.set_engine("V8").set_wheels(4).build()
3.3.3 单例模式
class DatabaseConnection:
    _instance = None
    
    def __new__(cls, connection_str: str):
        if not cls._instance:
            cls._instance = super().__new__(cls)
            cls._instance.conn = connect(connection_str)
        return cls._instance
    
    def __init__(self, connection_str: str):
        """虽然__new__控制实例创建,但仍需__init__"""
        # 注意:单例模式下__init__可能被多次调用
        pass

3.4构造方法最佳实践

3.4.1 初始化层次规范
class ScientificInstrument:
    def __init__(self, model: str):
        # 第一层:基础属性
        self.model = model
        self._calibrated = False
        
        # 第二层:组件初始化
        self._init_sensors()
        self._init_data_logger()
        
        # 第三层:状态检查
        self._run_self_test()
    
    def _init_sensors(self):
        """初始化传感器组件"""
        self.temperature_sensor = Sensor("温度", "℃")
        self.pressure_sensor = Sensor("压力", "Pa")
    
    def _run_self_test(self):
        """开机自检"""
        if not all(sensor.ready for sensor in self.sensors):
            raise RuntimeError("传感器初始化失败")
3.4.2 参数验证模板
def validate_parameters(func):
    """构造方法参数验证装饰器"""
    def wrapper(self, *args, **kwargs):
        # 在__init__执行前进行参数验证
        if not args[1].isalpha():
            raise ValueError("名称必须全字母")
        return func(self, *args, **kwargs)
    return wrapper

class ValidatedClass:
    @validate_parameters
    def __init__(self, name: str):
        self.name = name
3.4.3 延迟初始化技术
class LazyInitDemo:
    def __init__(self, config_path: str):
        self.config_path = config_path
        self._config = None  # 延迟加载
        
    @property
    def config(self):
        if self._config is None:
            self._load_config()
        return self._config
    
    def _load_config(self):
        """实际加载配置"""
        with open(self.config_path) as f:
            self._config = json.load(f)

3.5构造方法常见错误案例

3.5.1 忘记调用父类构造方法
class Base:
    def __init__(self, x: int):
        self.x = x

class Derived(Base):
    def __init__(self, y: int):
        # super().__init__(y*2)  # 忘记调用导致属性缺失
        self.y = y

d = Derived(5)
print(d.x)  # ❌ AttributeError
3.5.2 循环依赖初始化
class A:
    def __init__(self):
        self.b = B()  # 在构造中创建B实例

class B:
    def __init__(self):
        self.a = A()  # 在构造中创建A实例

# 创建实例会导致无限递归
# a = A()
3.5.3 可变默认参数陷阱
class Dangerous:
    def __init__(self, items=[]):  # ❌ 危险:默认列表共享
        self.items = items
    
    def add(self, item):
        self.items.append(item)

d1 = Dangerous()
d1.add(1)
d2 = Dangerous()
print(d2.items)  # 输出[1],预期应为空列表

四、self关键字的双重角色

4.1 self的六大核心职责

角色实现方式示例代码
对象标识符方法内访问实例的唯一途径self.brand
属性载体承载实例特有的数据状态self._imei = ...
方法调用枢纽实现方法间的协同工作self.__check_security()
生命周期管理者控制对象从创建到销毁的资源self.__del__()
动态扩展接口支持运行时添加属性和方法self.new_feature = lambda: ...
多态实现基础通过不同self对象实现行为多样性obj1.method() vs obj2.method()

4.2 self访问机制图解

[对象内存结构]
+-------------------+
| MobilePhone实例   |
|-------------------|
| brand: "HUAWEI"   |
| _imei: "1234..."  |
| __secret_code: "" |
+-------------------+
          ↑
          | self引用
+-------------------+
| verify_imei方法   |
|-------------------|
| input_imei参数    |
| return比较结果    |
+-------------------+

4.3 三种典型self使用场景

场景1:属性初始化

def __init__(self, name):
    self.name = name  # ✅ 正确绑定属性
    # name = name    # ❌ 错误:局部变量

场景2:方法间调用

def call(self, number):
    self.__check_network()  # 调用私有方法
    print(f"呼叫{number}")

def __check_network(self):
    if self.signal < 1:
        raise ConnectionError("信号强度不足")

场景3:实现链式调用

class MessageBuilder:
    def __init__(self):
        self.content = []
    
    def add_text(self, text):
        self.content.append(text)
        return self  # 返回self实现链式
    
    def add_image(self, url):
        self.content.append(f"<img src='{url}'>")
        return self

# 使用示例
builder = MessageBuilder()
html = builder.add_text("Hello").add_image("pic.jpg").content

五、成员变量管理策略

5.1 变量类型对照表

变量类型定义位置访问方式生命周期内存分配
类变量类顶层类/实例均可访问与类共存单份共享
实例变量init/方法中仅实例访问随对象销毁每个实例独立
保护变量前缀单下划线约定不直接访问同实例变量同实例变量
私有变量前缀双下划线类内部访问同实例变量同实例变量

5.2 变量操作最佳实践

class BankAccount:
    __interest_rate = 0.03  # 类私有变量
    
    def __init__(self, owner: str):
        self.owner = owner
        self.__balance = 0.0  # 实例私有变量
        
    @classmethod
    def set_rate(cls, new_rate: float):
        """类方法修改类变量"""
        if not 0 < new_rate < 1:
            raise ValueError("利率超出合理范围")
        cls.__interest_rate = new_rate
    
    def deposit(self, amount: float):
        """实例方法操作私有变量"""
        if amount <= 0:
            raise ValueError("存款金额必须为正数")
        self.__balance += amount
    
    @property
    def balance(self):
        """属性访问器保护数据"""
        return round(self.__balance, 2)

六、成员方法全景图

6.1 方法类型矩阵

方法类型装饰器self参数访问权限典型应用
实例方法必须访问所有实例成员主要业务逻辑
类方法@classmethodcls操作类变量工厂模式、配置修改
静态方法@staticmethod不能访问实例/类变量工具函数
魔法方法多种形式特殊操作str、__eq__等
抽象方法@abstractmethodself需子类实现定义接口规范

6.2 综合方法示例

class SocialMediaPost:
    platform = "未知平台"  # 类变量
    
    def __init__(self, content: str):
        self.content = content
        self.__views = 0  # 私有变量
        
    def show(self) -> None:
        """实例方法:展示内容"""
        self.__increase_views()
        print(f"{self.platform}内容:{self.content}")
    
    def __increase_views(self) -> None:
        """私有方法:记录浏览量"""
        self.__views += 1
    
    @classmethod
    def change_platform(cls, new_platform: str) -> None:
        """类方法:修改平台"""
        cls.platform = new_platform
    
    @staticmethod
    def validate_content(content: str) -> bool:
        """静态方法:内容审核"""
        return len(content) <= 1000 and not any(c in content for c in "!@#$")
    
    def __str__(self) -> str:
        """魔法方法:字符串表示"""
        return f"<{self.platform}帖子:{self.content[:20]}...>"

七、魔术方法(Magic Methods)解析

7.1 常用魔术方法分类表

类别方法触发场景示例
对象表示__str__, __repr__print/交互式显示print(obj)
数学运算__add__, __sub__运算符操作obj1 + obj2
比较运算__eq__, __lt__比较操作obj1 == obj2
容器行为__len__, __getitem__容器操作len(obj), obj[0]
上下文管理__enter__, __exit__with语句块with obj as f:
属性管理__getattr__, __setattr__属性访问obj.attr

7.2 核心魔术方法实现示例

class Vector3D:
    def __init__(self, x: float, y: float, z: float):
        self.x = x
        self.y = y
        self.z = z
    
    # 字符串表示
    def __str__(self) -> str:
        return f"Vector3D({self.x}, {self.y}, {self.z})"
    
    def __repr__(self) -> str:
        return f"<Vector3D x:{self.x} y:{self.y} z:{self.z}>"
    
    # 数学运算
    def __add__(self, other):
        return Vector3D(
            self.x + other.x,
            self.y + other.y,
            self.z + other.z
        )
    
    def __mul__(self, scalar: float):
        return Vector3D(
            self.x * scalar,
            self.y * scalar,
            self.z * scalar
        )
    
    # 比较运算
    def __eq__(self, other) -> bool:
        return (self.x, self.y, self.z) == (other.x, other.y, other.z)
    
    # 容器模拟
    def __getitem__(self, index: int) -> float:
        return [self.x, self.y, self.z][index]
    
    def __len__(self) -> int:
        return 3

# 使用示例
v1 = Vector3D(1, 2, 3)
v2 = Vector3D(4, 5, 6)
print(v1 + v2)        # 输出: Vector3D(5, 7, 9)
print(v1 * 2)         # 输出: Vector3D(2, 4, 6)
print(v1[0])          # 输出: 1.0
print(len(v1))        # 输出: 3

八、封装机制深入探讨

8.1 封装实现三级防护

访问级别命名方式可见范围示例
公有成员无下划线完全公开self.value
保护成员单下划线前缀类及子类内部self._protected
私有成员双下划线前缀仅类内部self.__private

8.2 私有变量实现原理

class SecuritySystem:
    def __init__(self):
        self.__alarm_code = "1234"  # 私有属性
        
    def check_code(self, code: str) -> bool:
        return self.__alarm_code == code

# 名称改编验证
obj = SecuritySystem()
print(dir(obj))  
# 输出包含 '_SecuritySystem__alarm_code',证明私有变量被改编

8.3 属性访问控制最佳实践

class TemperatureSensor:
    def __init__(self):
        self._current_temp = 0.0  # 保护属性
        self.__calibration = 1.0  # 私有属性
    
    @property
    def temperature(self) -> float:
        """对外暴露的温度值(应用校准)"""
        return self._current_temp * self.__calibration
    
    @temperature.setter
    def temperature(self, value: float):
        """温度值设置器(带范围验证)"""
        if not (-200 <= value <= 1000):
            raise ValueError("温度值超出合理范围")
        self._current_temp = value
    
    @property
    def calibration(self) -> float:
        """只读属性"""
        return self.__calibration
    
    def adjust_calibration(self, factor: float):
        """校准方法(带权限验证)"""
        if not (0.5 <= factor <= 2.0):
            raise ValueError("校准系数需在0.5-2.0之间")
        self.__calibration = factor

# 使用示例
sensor = TemperatureSensor()
sensor.temperature = 25.5  # 通过setter方法
print(sensor.temperature)  # 输出校准后温度
# sensor.calibration = 1.2  # ❌ 报错:只读属性

九、综合案例:银行账户系统

9.1 类设计规范

class BankAccount:
    """银行账户类(演示封装与魔术方法)"""
    
    def __init__(self, account_holder: str, initial_balance: float = 0):
        self.holder = account_holder
        self.__balance = initial_balance  # 私有属性
        self.__transaction_log = []       # 交易记录
    
    def __str__(self) -> str:
        return f"账户持有人:{self.holder},余额:¥{self.balance:.2f}"
    
    def __repr__(self) -> str:
        return f"<BankAccount {self.holder[:3]}***>"
    
    def __add__(self, amount: float):
        """支持 + 运算符存款"""
        self.deposit(amount)
        return self
    
    @property
    def balance(self) -> float:
        """余额只读属性"""
        return self.__balance
    
    def deposit(self, amount: float):
        """存款操作"""
        if amount <= 0:
            raise ValueError("存款金额必须为正数")
        self.__balance += amount
        self.__log_transaction(f"存款 ¥{amount:.2f}")
    
    def withdraw(self, amount: float):
        """取款操作"""
        if amount <= 0:
            raise ValueError("取款金额必须为正数")
        if amount > self.__balance:
            raise ValueError("余额不足")
        self.__balance -= amount
        self.__log_transaction(f"取款 ¥{amount:.2f}")
    
    def __log_transaction(self, message: str):
        """私有方法记录交易"""
        from datetime import datetime
        timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        self.__transaction_log.append(f"[{timestamp}] {message}")
    
    def get_statement(self) -> str:
        """获取对账单"""
        return "\n".join(self.__transaction_log)

# 使用示例
account = BankAccount("张三", 1000)
account += 500  # 使用__add__魔术方法
account.withdraw(300)
print(account)
print(account.get_statement())

十、进阶封装技巧

10.1 动态属性管理

class SmartConfig:
    """动态属性管理示例"""
    
    __allowed_keys = {"timeout", "retries", "debug"}
    
    def __init__(self):
        self.__data = {}
    
    def __setattr__(self, name: str, value):
        """拦截属性设置"""
        if name.startswith("_"):
            super().__setattr__(name, value)
        elif name in self.__allowed_keys:
            self.__data[name] = value
        else:
            raise AttributeError(f"禁止设置属性 {name}")
    
    def __getattr__(self, name: str):
        """拦截属性访问"""
        if name in self.__data:
            return self.__data[name]
        raise AttributeError(f"属性 {name} 不存在")
    
    def __delattr__(self, name: str):
        """拦截属性删除"""
        if name in self.__data:
            del self.__data[name]
        else:
            super().__delattr__(name)

# 使用示例
config = SmartConfig()
config.timeout = 30  # ✅ 允许
# config.color = "red" # ❌ 触发AttributeError

10.2 接口隔离原则

from abc import ABC, abstractmethod

class DatabaseConnector(ABC):
    """数据库连接器抽象类"""
    
    @abstractmethod
    def connect(self):
        pass
    
    @abstractmethod
    def execute_query(self, sql: str):
        pass

class MySQLConnector(DatabaseConnector):
    """具体实现类"""
    
    def __init__(self, host: str):
        self.__host = host  # 私有属性
        self.__connection = None
    
    def connect(self):
        self.__connection = f"连接到 {self.__host}"
    
    def execute_query(self, sql: str):
        if not self.__connection:
            raise ConnectionError("请先建立连接")
        print(f"执行SQL: {sql}")

# 使用示例
connector = MySQLConnector("localhost")
connector.connect()
connector.execute_query("SELECT * FROM users")

十一、魔术方法与封装结合实践

11.1 上下文管理器实现

class DatabaseTransaction:
    """数据库事务管理器(演示__enter__/__exit__)"""
    
    def __init__(self, db_conn):
        self.conn = db_conn
        self.__transaction_active = False
    
    def __enter__(self):
        """进入上下文时启动事务"""
        self.conn.execute("BEGIN TRANSACTION")
        self.__transaction_active = True
        return self
    
    def __exit__(self, exc_type, exc_val, exc_tb):
        """退出上下文时提交或回滚"""
        if self.__transaction_active:
            if exc_type:
                self.conn.execute("ROLLBACK")
                print("事务回滚")
            else:
                self.conn.execute("COMMIT")
                print("事务提交")
        self.__transaction_active = False
    
    def execute(self, sql: str):
        """执行SQL语句"""
        if not self.__transaction_active:
            raise RuntimeError("事务未启动")
        print(f"执行: {sql}")

# 使用示例
class MockDB:
    def execute(self, cmd):
        print(f"数据库执行: {cmd}")

with DatabaseTransaction(MockDB()) as tx:
    tx.execute("INSERT INTO users VALUES (1, 'Alice')")
    tx.execute("UPDATE accounts SET balance = 100")
# 自动提交事务

11.2 不可变数据类

class ImmutablePoint:
    """通过封装实现不可变类"""
    
    __slots__ = ['__x', '__y']
    
    def __init__(self, x: float, y: float):
        self.__x = x
        self.__y = y
    
    @property
    def x(self) -> float:
        return self.__x
    
    @property
    def y(self) -> float:
        return self.__y
    
    def __setattr__(self, name, value):
        if name.startswith("_"):
            super().__setattr__(name, value)
        else:
            raise AttributeError("不可变对象禁止修改属性")
    
    def __repr__(self) -> str:
        return f"Point({self.x}, {self.y})"

# 使用示例
p = ImmutablePoint(3, 4)
print(p.x, p.y)  # 输出: 3 4
# p.x = 5  # ❌ 触发AttributeError

十二、最佳实践总结

12.1 魔术方法使用原则

  1. 按需实现:只实现业务需要的方法
  2. 保持直观:运算符重载要符合直觉
  3. 性能考量:避免在魔术方法中执行耗时操作
  4. 文档完善:清晰说明特殊行为

12.2 封装设计规范

  1. 最小暴露原则:只公开必要接口
  2. 数据验证前置:在setter方法中验证输入
  3. 访问权限分级:合理使用public/protected/private
  4. 保持一致性:类接口设计风格统一

十三、电商系统案例

13.1 类关系设计

1
1
1
*
User
+user_id: str
-_password: str
+cart: ShoppingCart
+add_to_cart()
+checkout()
Product
+sku: str
+price: float
-_stock: int
+restock()
ShoppingCart
-items: dict
+add_item()
+remove_item()
+calculate_total()

13.2 核心代码实现

class Product:
    def __init__(self, sku: str, name: str, price: float):
        self.sku = sku
        self.name = name
        self.price = price
        self._stock = 0
    
    def restock(self, quantity: int) -> None:
        """库存补货(通过self维护状态)"""
        if quantity <= 0:
            raise ValueError("补货数量必须为正")
        self._stock += quantity
    
    @property
    def stock_info(self) -> str:
        """库存状态属性"""
        if self._stock > 100:
            return "充足"
        elif self._stock > 20:
            return "正常"
        return "需补货"

class ShoppingCart:
    def __init__(self):
        self.items = {}  # {Product: quantity}
    
    def add_item(self, product: Product, qty: int = 1) -> None:
        """添加商品到购物车"""
        if product._stock < qty:
            raise ValueError(f"{product.name}库存不足")
        self.items[product] = self.items.get(product, 0) + qty
        product._stock -= qty  # 修改商品库存
    
    def total_price(self) -> float:
        """计算总价(self遍历所有商品)"""
        return sum(p.price * q for p, q in self.items.items())

class User:
    def __init__(self, user_id: str):
        self.user_id = user_id
        self.cart = ShoppingCart()
    
    def checkout(self) -> float:
        """结账操作"""
        total = self.cart.total_price()
        self.cart = ShoppingCart()  # 清空购物车
        return total

# 使用示例
iphone = Product("P1001", "iPhone 15", 7999)
user = User("U10001")

user.cart.add_item(iphone, 2)
print(f"订单总价:¥{user.checkout():.2f}")  # 输出:¥15998.00
print(iphone.stock_info)  # 输出:需补货(假设初始库存为0)

十四、最佳实践与调试技巧

14.1 常见错误排查表

错误现象可能原因解决方案
AttributeError忘记self前缀访问属性检查所有属性访问是否带self
TypeError缺少参数方法定义遗漏self参数确保实例方法第一个参数是self
意外修改类变量通过实例修改类变量使用类名或cls访问类变量
方法互相覆盖继承链方法命名冲突使用super()正确调用父类方法
内存泄漏循环引用未释放使用weakref或显式解除引用

14.2 调试技巧

  1. 查看对象状态
print(vars(user))  # 查看实例所有属性
  1. 跟踪方法调用
import trace

tracer = trace.Trace(countfuncs=1)
tracer.runfunc(user.add_to_cart, product, 2)
  1. 检查类型提示
mypy your_script.py  # 静态类型检查

十五、继承机制深度解析

15.1 继承核心概念

class Vehicle:
    """交通工具基类"""
    
    def __init__(self, brand: str, fuel_type: str):
        self.brand = brand          # 品牌
        self._fuel_type = fuel_type # 燃料类型(保护属性)
        self.__mileage = 0          # 里程数(私有属性)
    
    def drive(self, km: float) -> None:
        """驾驶方法"""
        self.__mileage += km
        print(f"行驶{km}公里,总里程{self.__mileage}")

class ElectricCar(Vehicle):
    """电动汽车子类"""
    
    def __init__(self, brand: str, battery_cap: float):
        super().__init__(brand, "电力")  # 调用父类构造
        self.battery_capacity = battery_cap  # 新增属性
    
    def charge(self, minutes: int) -> float:
        """充电方法(子类特有)"""
        charged = minutes * 0.2  # 每分钟充0.2度
        print(f"已充电{charged:.1f}度")
        return charged
    
    # 重写父类方法
    def drive(self, km: float) -> None:
        super().drive(km)  # 复用父类逻辑
        print("零排放驾驶!")

# 使用示例
tesla = ElectricCar("Tesla", 75.0)
tesla.drive(150)  # 输出:行驶150公里... 零排放驾驶!

15.2 继承类型对比

继承类型特点示例
单继承只有一个直接父类class A(B): ...
多重继承多个直接父类class C(A, B): ...
多级继承形成继承链class D(C):C(B)B(A)
接口继承只继承方法签名(抽象基类)class E(ABC): ...

十六、类型注解全面指南

16.1 基础类型注解

class Student:
    # 类变量类型注解
    school: str = "清华大学"
    
    def __init__(self, name: str, age: int) -> None:
        # 实例变量类型注解
        self.name: str = name
        self.age: int = age
        self.scores: dict[str, float] = {}  # 字典注解
    
    def add_score(self, subject: str, score: float) -> bool:
        """方法参数与返回类型注解"""
        if 0 <= score <= 100:
            self.scores[subject] = score
            return True
        return False
    
    def get_average(self) -> float:
        """返回类型注解"""
        return sum(self.scores.values()) / len(self.scores) if self.scores else 0.0

16.2 高级类型注解技巧

from typing import Union, Optional, List, TypeVar

T = TypeVar('T', bound='Animal')  # 类型变量

class Animal:
    def speak(self) -> str:
        raise NotImplementedError

class Dog(Animal):
    def speak(self) -> str:
        return "汪汪!"

class AnimalShelter:
    def __init__(self) -> None:
        self.__animals: List[Animal] = []
    
    def add_animal(self, animal: T) -> None:
        """泛型方法注解"""
        self.__animals.append(animal)
    
    def find_by_type(self, animal_type: type[T]) -> Optional[T]:
        """类型参数与返回注解"""
        for a in self.__animals:
            if isinstance(a, animal_type):
                return a
        return None

# 使用示例
shelter = AnimalShelter()
shelter.add_animal(Dog())
found_dog = shelter.find_by_type(Dog)
if found_dog:
    print(found_dog.speak())  # 输出:汪汪!

十七、继承与类型注解结合实践

17.1 抽象基类示例

from abc import ABC, abstractmethod
from typing import Protocol

class Drawable(Protocol):
    """接口协议定义(Python 3.8+)"""
    
    @abstractmethod
    def draw(self) -> None:
        pass
    
    @property
    @abstractmethod
    def area(self) -> float:
        pass

class Shape(ABC):
    """抽象基类"""
    
    def __init__(self, color: str) -> None:
        self.color = color
    
    @abstractmethod
    def draw(self) -> None:
        pass
    
    @property
    @abstractmethod
    def area(self) -> float:
        pass

class Circle(Shape):
    """具体实现类"""
    
    def __init__(self, radius: float, color: str) -> None:
        super().__init__(color)
        self.radius = radius
    
    def draw(self) -> None:
        print(f"绘制{self.color}的圆形,半径{self.radius}")
    
    @property
    def area(self) -> float:
        return 3.14159 * self.radius ** 2

# 类型检查示例
def render(shapes: list[Drawable]) -> None:
    for shape in shapes:
        shape.draw()
        print(f"面积:{shape.area:.2f}")

render([Circle(5, "红色")])

17.2 泛型继承应用

from typing import Generic, TypeVar, List

T = TypeVar('T')

class Repository(Generic[T]):
    """泛型仓储基类"""
    
    def __init__(self) -> None:
        self._items: List[T] = []
    
    def add(self, item: T) -> None:
        self._items.append(item)
    
    def get_all(self) -> List[T]:
        return self._items.copy()

class User:
    def __init__(self, name: str) -> None:
        self.name = name

class UserRepository(Repository[User]):
    """用户仓储实现"""
    
    def find_by_name(self, name: str) -> Optional[User]:
        for user in self._items:
            if user.name == name:
                return user
        return None

# 使用示例
repo = UserRepository()
repo.add(User("Alice"))
repo.add(User("Bob"))
print([u.name for u in repo.get_all()])  # 输出:['Alice', 'Bob']

十八、最佳实践与工具链

18.1 继承设计原则

原则说明示例
里氏替换原则子类应完全实现父类接口重写方法不修改返回值类型
接口隔离原则保持接口最小化使用多个特定接口代替单个大接口
组合优于继承优先使用组合关系通过属性包含其他类实例
避免多重继承菱形问题使用Mixin类代替多重继承定义可复用功能模块

18.2 类型注解检查工具

  1. mypy静态检查
# 安装
pip install mypy

# 检查命令
mypy your_script.py
  1. Pylance类型提示(VSCode扩展)
// .vscode/settings.json
{
  "python.analysis.typeCheckingMode": "strict"
}
  1. Pyright检查配置
npm install -g pyright
pyright your_script.py

十九、综合案例:图形系统设计

19.1 类继承结构

«abstract»
Shape
+color: str
+draw()
+area()
Circle
+radius: float
+draw()
+area()
Rectangle
+width: float
+height: float
+draw()
+area()
«mixin»
Movable
+position: tuple[float, float]
+move(dx: float, dy: float)

19.2 类型注解实现

from typing import Protocol, Tuple

class Positional(Protocol):
    """位置协议"""
    
    @property
    def position(self) -> Tuple[float, float]:
        ...
    
    def move(self, dx: float, dy: float) -> None:
        ...

class Shape:
    def __init__(self, color: str) -> None:
        self.color = color
    
    def draw(self) -> None:
        raise NotImplementedError
    
    @property
    def area(self) -> float:
        raise NotImplementedError

class MovableMixin:
    """可移动功能混入类"""
    
    def __init__(self) -> None:
        self._position: Tuple[float, float] = (0.0, 0.0)
    
    @property
    def position(self) -> Tuple[float, float]:
        return self._position
    
    def move(self, dx: float, dy: float) -> None:
        self._position = (self._position[0]+dx, self._position[1]+dy)

class Rectangle(Shape, MovableMixin):
    """可移动矩形"""
    
    def __init__(self, color: str, width: float, height: float) -> None:
        super().__init__(color)
        MovableMixin.__init__(self)
        self.width = width
        self.height = height
    
    def draw(self) -> None:
        print(f"在位置{self.position}绘制{self.color}矩形")
    
    @property
    def area(self) -> float:
        return self.width * self.height

def move_shape(shape: Positional, dx: float, dy: float) -> None:
    """使用协议类型注解"""
    shape.move(dx, dy)

# 使用示例
rect = Rectangle("蓝色", 10, 5)
move_shape(rect, 2.5, 3.0)
rect.draw()  # 输出:在位置(2.5, 3.0)绘制蓝色矩形

二十、继承与类型注解注意事项

20.1 继承常见问题

问题解决方案
父类构造未正确调用使用super().init()显式调用
方法重写破坏父类约束遵循里氏替换原则,保持接口一致性
多重继承顺序冲突使用方法解析顺序(MRO)检查
过度继承导致耦合优先使用组合关系替代复杂继承链

20.2 类型注解陷阱

问题解决方案
循环引用类型提示使用字符串注解或TypeVar
泛型参数不匹配明确指定泛型类型参数
动态类型绕过检查使用强制类型转换或类型保护
第三方库缺少类型提示添加类型存根文件(.pyi)

学习路线建议

  1. 基础阶段

    • 掌握类与对象的关系
    • 理解self的运行机制
    • 区分类变量与实例变量
  2. 进阶阶段

    • 实现继承与多态
    • 熟练使用属性装饰器
    • 掌握特殊魔法方法
  3. 高级阶段

    • 设计模式应用(工厂、单例等)
    • 元类编程
    • 实现ORM映射
  4. 实战项目

    • 图书馆管理系统
    • 电商交易平台
    • 游戏角色管理系统
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值