未记录事实核验 · 状态:维护中

记录仅说明核验时间与维护状态,不保证适用于所有环境;使用前请留意正文中的版本、适用条件与风险提示。

warning 适用边界与维护说明

本文适合已掌握函数、作用域和装饰器的读者进阶学习Python对象机制,正文提供教学数据,不依赖真实业务材料;本次仅作结构与代码静态审阅,未执行示例或作外部事实核验。各节示例并非全部可独立运行:描述符、策略模式和SOLID示例复用前文导入,且DataPoint、DataProcessor在不同章节被重新定义,宜按章节保留所需上下文,不作为统一项目直接复用。银行账户仅演示封装及部分加锁,冻结检查、每日限额重置和对账单读取不保证完整并发一致性;Vector作为字典键或集合元素期间不得修改坐标,LoggedAttribute的值和日志由所有实例共享。EnhancedProcessor仅以hash(str(data))作缓存键,不能保证不同输入不会误命中;DataSet修改已有数据点或直接修改集合后不会自动使统计缓存失效,返回的统计字典也不是隔离副本。矩阵示例应使用规则的二维数值列表,避免替换行导致已记录的维度失效。金额、年龄和评分的共同统计及归一化仅展示方法调用,不具有共同业务统计含义;默认哈希分类编码不适用于稳定、无碰撞编码任务。sys.getsizeof比较仅反映浅层对象大小,不是完整内存占用测量;数据库连接及报告生成示例为模拟行为,不提供真实数据库访问或PDF、Excel文件生成。页面两处更新时间不一致,不能据此判断实际修订时间。

Python面向对象编程 - OOP原理与实现机制详解

abstract 内容概览

  • 核心概念:类与对象的内存模型、方法解析顺序(MRO)、特殊方法协议
  • 技术深度:封装机制、继承链、多态实现、描述符协议、元类机制
  • 前置知识:Python函数编程、变量作用域、装饰器
  • 应用场景:数据模型设计、框架开发、设计模式实现、API封装
  • 学习重点:理解Python对象模型和动态特性,掌握OOP设计原则

Python对象模型基础

核心概念定义

**面向对象编程(OOP)**是一种编程范式,通过对象来组织代码。对象封装数据(属性)和行为(方法),支持抽象、封装、继承和多态四个基本特性。

Python中的一切皆对象:

# 验证Python中一切皆对象的特性
import sys

# 数字是对象
num = 42
print(f"数字对象:{type(num)}, ID: {id(num)}")
print(f"数字对象的方法:{[m for m in dir(num) if not m.startswith('_')][:5]}")

# 函数是对象
def example_func():
    return "Hello"
    
print(f"\n函数对象:{type(example_func)}")
print(f"函数对象属性:{example_func.__name__}, {example_func.__doc__}")

# 类也是对象(由元类创建)
class ExampleClass:
    pass
    
print(f"\n类对象:{type(ExampleClass)}")
print(f"类的元类:{type(type(ExampleClass))}")

类与对象的内存模型

class DataPoint:
    """数据点类 - 演示Python对象的内存结构"""
    
    class_var = "共享数据"  # 类变量,存储在类对象中
    
    def __init__(self, x, y):
        self.x = x  # 实例变量,存储在实例的__dict__中
        self.y = y
    
    def distance_from_origin(self):
        return (self.x ** 2 + self.y ** 2) ** 0.5

# 创建实例并分析内存结构
point1 = DataPoint(3, 4)
point2 = DataPoint(5, 12)

print("=== 对象内存结构分析 ===")
print(f"类对象 ID: {id(DataPoint)}")
print(f"实例1 ID: {id(point1)}, 实例2 ID: {id(point2)}")
print(f"实例1.__dict__: {point1.__dict__}")
print(f"实例2.__dict__: {point2.__dict__}")
print(f"类变量地址: {id(DataPoint.class_var)}")
print(f"通过实例访问类变量: {id(point1.class_var)}")

# 方法解析顺序(Method Resolution Order)
print(f"\n=== MRO分析 ===")
print(f"DataPoint MRO: {DataPoint.__mro__}")
print(f"方法查找路径: {[cls.__name__ for cls in DataPoint.__mro__]}")

类定义与实例化机制

类的创建过程

Python类的创建过程可概括为:

  1. 确定类名、基类和元类,并准备类命名空间
  2. 执行类体,填充类的命名空间
  3. 调用元类(通常为type),使用类名、基类和已填充的命名空间创建类对象
  4. 应用类装饰器(如有),并将结果绑定到类名
import dis
from types import FunctionType

class DataModel:
    """数据模型类 - 演示类的创建和实例化过程"""
    
    # 类属性(存储在类对象中)
    model_version = "1.0"
    _instances = []  # 类级别的实例追踪
    
    def __init__(self, name, data_type):
        """实例化方法 - 初始化对象状态"""
        self.name = name
        self.data_type = data_type
        self._created_at = __import__('time').time()
        
        # 将实例添加到类级别的追踪列表
        DataModel._instances.append(self)
        
    def __new__(cls, *args, **kwargs):
        """对象创建方法 - 在__init__之前调用"""
        print(f"创建{cls.__name__}对象实例")
        instance = super().__new__(cls)
        return instance
    
    def __repr__(self):
        """对象的官方字符串表示"""
        return f"DataModel(name='{self.name}', type='{self.data_type}')"
    
    def __str__(self):
        """对象的非正式字符串表示"""
        return f"{self.name}数据模型 (类型: {self.data_type})"
    
    @classmethod
    def get_instance_count(cls):
        """类方法 - 获取实例数量"""
        return len(cls._instances)
    
    @staticmethod
    def validate_data_type(data_type):
        """静态方法 - 验证数据类型"""
        valid_types = ['numerical', 'categorical', 'text', 'datetime']
        return data_type in valid_types

# 演示对象创建过程
print("=== 对象创建和初始化过程 ===")
model1 = DataModel("用户行为", "categorical")
model2 = DataModel("销售额", "numerical")

print(f"\n创建的实例: {DataModel._instances}")
print(f"实例数量: {DataModel.get_instance_count()}")
print(f"数据类型验证: {DataModel.validate_data_type('text')}")

# 分析对象的内部结构
print(f"\n=== 对象内部结构分析 ===")
print(f"实例属性: {model1.__dict__}")
print(f"类属性: {[attr for attr in dir(DataModel) if not attr.startswith('__') and not callable(getattr(DataModel, attr))]}")
print(f"实例方法: {[method for method in dir(model1) if callable(getattr(model1, method)) and not method.startswith('_')]}")

特殊方法(魔术方法)详解

class Vector:
    """向量类 - 演示特殊方法的实现"""
    
    def __init__(self, x, y):
        self.x = x
        self.y = y
    
    def __repr__(self):
        return f"Vector({self.x}, {self.y})"
    
    def __str__(self):
        return f"({self.x}, {self.y})"
    
    def __add__(self, other):
        """向量加法"""
        if isinstance(other, Vector):
            return Vector(self.x + other.x, self.y + other.y)
        return NotImplemented
    
    def __mul__(self, scalar):
        """向量标量乘法"""
        if isinstance(scalar, (int, float)):
            return Vector(self.x * scalar, self.y * scalar)
        return NotImplemented
    
    def __rmul__(self, scalar):
        """右乘运算"""
        return self.__mul__(scalar)
    
    def __abs__(self):
        """向量的模长"""
        return (self.x ** 2 + self.y ** 2) ** 0.5
    
    def __bool__(self):
        """布尔值转换"""
        return bool(abs(self))
    
    def __eq__(self, other):
        """相等比较"""
        if isinstance(other, Vector):
            return self.x == other.x and self.y == other.y
        return False
    
    def __hash__(self):
        """坐标哈希演示:x、y可变,作为字典键或集合元素期间不得修改坐标"""
        return hash((self.x, self.y))
    
    def __getitem__(self, index):
        """索引访问"""
        if index == 0:
            return self.x
        elif index == 1:
            return self.y
        else:
            raise IndexError("Vector索引只能是0或1")
    
    def __len__(self):
        """长度(维度)"""
        return 2
    
    def __iter__(self):
        """迭代器协议"""
        yield self.x
        yield self.y

# 演示特殊方法的使用
print("=== 特殊方法演示 ===")
v1 = Vector(3, 4)
v2 = Vector(1, 2)

print(f"向量表示: {repr(v1)}, {str(v1)}")
print(f"向量加法: {v1 + v2}")
print(f"标量乘法: {v1 * 2}, {3 * v1}")
print(f"向量模长: {abs(v1)}")
print(f"布尔转换: {bool(v1)}, {bool(Vector(0, 0))}")
print(f"相等比较: {v1 == v2}, {v1 == Vector(3, 4)}")
print(f"索引访问: v1[0]={v1[0]}, v1[1]={v1[1]}")
print(f"迭代: {list(v1)}")
print(f"哈希值: {hash(v1)}")

封装机制与数据保护

属性访问控制

from datetime import datetime, timedelta
from decimal import Decimal, ROUND_HALF_UP
import threading
import logging

class SecureBankAccount:
    """银行账户教学示例 - 演示封装及部分加锁操作,不代表完整金融或线程安全实现"""
    
    # 类变量:银行基础配置
    _bank_name = "安全银行"
    _interest_rate = Decimal('0.03')  # 年利率3%
    _min_balance = Decimal('0')
    _max_daily_withdrawal = Decimal('50000')
    
    def __init__(self, account_number, owner_name, initial_balance=0):
        # 公共属性
        self.account_number = account_number
        self.owner_name = owner_name
        
        # 受保护属性(约定:子类可以访问)
        self._created_at = datetime.now()
        self._last_transaction_time = None
        
        # 私有属性(名称修饰:外部难以直接访问)
        self.__balance = Decimal(str(initial_balance))
        self.__daily_withdrawal = Decimal('0')
        self.__daily_withdrawal_date = datetime.now().date()
        self.__transaction_history = []
        self.__is_frozen = False
        
        # 线程锁保护并发操作
        self.__lock = threading.Lock()
        
        # 记录账户创建
        self.__add_transaction("账户创建", Decimal('0'), self.__balance)
    
    @property
    def balance(self):
        """余额属性:只读访问"""
        with self.__lock:
            return float(self.__balance)
    
    @property
    def is_frozen(self):
        """冻结状态:只读访问"""
        return self.__is_frozen
    
    @property 
    def daily_withdrawal_remaining(self):
        """当日可提取余额"""
        self.__reset_daily_limit_if_needed()
        return float(self._max_daily_withdrawal - self.__daily_withdrawal)
    
    def __add_transaction(self, transaction_type, amount, balance_after):
        """私有方法:添加交易记录"""
        transaction = {
            'timestamp': datetime.now(),
            'type': transaction_type,
            'amount': float(amount),
            'balance_after': float(balance_after)
        }
        self.__transaction_history.append(transaction)
        self._last_transaction_time = transaction['timestamp']
    
    def __reset_daily_limit_if_needed(self):
        """私有方法:重置每日限额(如果需要)"""
        today = datetime.now().date()
        if self.__daily_withdrawal_date != today:
            self.__daily_withdrawal = Decimal('0')
            self.__daily_withdrawal_date = today
    
    def deposit(self, amount):
        """存款操作:余额更新在锁内,冻结检查尚未与更新原子化"""
        if self.__is_frozen:
            raise ValueError("账户已冻结,无法进行操作")
        
        amount = Decimal(str(amount))
        if amount <= 0:
            raise ValueError("存款金额必须大于0")
        
        with self.__lock:
            self.__balance += amount
            self.__add_transaction("存款", amount, self.__balance)
            return float(self.__balance)
    
    def withdraw(self, amount):
        """取款操作:包含各种限制检查"""
        if self.__is_frozen:
            raise ValueError("账户已冻结,无法进行操作")
        
        amount = Decimal(str(amount))
        if amount <= 0:
            raise ValueError("取款金额必须大于0")
        
        with self.__lock:
            # 检查余额
            if amount > self.__balance:
                raise ValueError(f"余额不足:当前余额{self.__balance},尝试提取{amount}")
            
            # 检查每日限额
            self.__reset_daily_limit_if_needed()
            if self.__daily_withdrawal + amount > self._max_daily_withdrawal:
                remaining = self._max_daily_withdrawal - self.__daily_withdrawal
                raise ValueError(f"超出每日取款限额:今日还可提取{remaining}")
            
            # 执行取款
            self.__balance -= amount
            self.__daily_withdrawal += amount
            self.__add_transaction("取款", -amount, self.__balance)
            return float(self.__balance)
    
    def freeze_account(self):
        """冻结账户"""
        with self.__lock:
            self.__is_frozen = True
            self.__add_transaction("账户冻结", Decimal('0'), self.__balance)
    
    def unfreeze_account(self):
        """解冻账户"""
        with self.__lock:
            self.__is_frozen = False
            self.__add_transaction("账户解冻", Decimal('0'), self.__balance)
    
    def get_statement(self, days=30):
        """获取账户对账单"""
        cutoff_date = datetime.now() - timedelta(days=days)
        
        recent_transactions = [
            t for t in self.__transaction_history 
            if t['timestamp'] >= cutoff_date
        ]
        
        return {
            'account_number': self.account_number,
            'owner': self.owner_name,
            'current_balance': float(self.__balance),
            'statement_period': f"最近{days}天",
            'transactions': recent_transactions
        }
    
    def __str__(self):
        return f"账户({self.account_number}) - {self.owner_name}: ¥{self.balance:.2f}"
    
    def __repr__(self):
        return f"SecureBankAccount('{self.account_number}', '{self.owner_name}', {self.balance})"

# 演示封装机制
print("=== 银行账户封装机制演示 ===")
account = SecureBankAccount("ACC001", "张三", 10000)

# 正常操作
print(f"初始状态: {account}")
print(f"存款1000: 余额 = {account.deposit(1000)}")
print(f"取款500: 余额 = {account.withdraw(500)}")

# 属性访问
print(f"\n当前余额(只读): {account.balance}")
print(f"今日剩余可提取额度: {account.daily_withdrawal_remaining}")
print(f"账户创建时间: {account._created_at}")

# 尝试直接访问私有属性(会失败或显示修饰后的名称)
print(f"\n=== 私有属性访问测试 ===")
try:
    print(account.__balance)  # 这会引发AttributeError
except AttributeError:
    print("无法直接访问 __balance(这是正确的行为)")

# 但可以通过名称修饰访问(不推荐这样做)
print(f"通过名称修饰访问: {account._SecureBankAccount__balance}")

# 获取对账单
statement = account.get_statement()
print(f"\n=== 账户对账单 ===")
for transaction in statement['transactions']:
    print(f"{transaction['timestamp'].strftime('%Y-%m-%d %H:%M')} - {transaction['type']}: {transaction['amount']}")

描述符协议高级应用

class ValidatedAttribute:
    """描述符:实现属性验证"""
    
    def __init__(self, validation_func=None, doc=None):
        self.validation_func = validation_func
        self.doc = doc
    
    def __set_name__(self, owner, name):
        self.name = name
        self.private_name = '_' + name
    
    def __get__(self, obj, objtype=None):
        if obj is None:
            return self
        return getattr(obj, self.private_name)
    
    def __set__(self, obj, value):
        if self.validation_func:
            self.validation_func(value)
        setattr(obj, self.private_name, value)
    
    def __delete__(self, obj):
        raise AttributeError(f"无法删除属性 {self.name}")

class LoggedAttribute:
    """描述符:演示访问日志;当前值和日志由所有实例共享,并非实例独立存储"""
    
    def __init__(self, initial_value=None):
        self.value = initial_value
        self.access_log = []
    
    def __set_name__(self, owner, name):
        self.name = name
    
    def __get__(self, obj, objtype=None):
        if obj is None:
            return self
        
        import time
        self.access_log.append({
            'operation': 'get',
            'timestamp': time.time(),
            'object_id': id(obj)
        })
        return self.value
    
    def __set__(self, obj, value):
        import time
        old_value = self.value
        self.value = value
        self.access_log.append({
            'operation': 'set',
            'timestamp': time.time(),
            'object_id': id(obj),
            'old_value': old_value,
            'new_value': value
        })

# 验证函数
def validate_positive(value):
    if not isinstance(value, (int, float)) or value <= 0:
        raise ValueError(f"值必须是正数,得到: {value}")

def validate_string_length(value, min_len=1, max_len=100):
    if not isinstance(value, str) or not (min_len <= len(value) <= max_len):
        raise ValueError(f"字符串长度必须在{min_len}-{max_len}之间")

class DataRecord:
    """使用描述符的数据记录类"""
    
    # 使用描述符定义属性
    price = ValidatedAttribute(validate_positive, "产品价格(必须为正数)")
    quantity = ValidatedAttribute(validate_positive, "数量(必须为正数)")
    description = ValidatedAttribute(
        lambda x: validate_string_length(x, 1, 200), 
        "产品描述"
    )
    
    # 带日志的属性
    status = LoggedAttribute("active")
    
    def __init__(self, price, quantity, description):
        self.price = price
        self.quantity = quantity  
        self.description = description
        self._created_at = datetime.now()
    
    @property
    def total_value(self):
        """计算属性:总价值"""
        return self.price * self.quantity
    
    def get_access_log(self):
        """获取status字段的访问日志"""
        return DataRecord.status.access_log

# 演示描述符应用
print("=== 描述符协议演示 ===")

try:
    record = DataRecord(29.99, 10, "高质量数据分析工具")
    print(f"记录创建成功: {record.description}")
    print(f"总价值: {record.total_value}")
    
    # 触发验证
    record.price = 39.99
    print(f"价格更新成功: {record.price}")
    
    # 访问带日志的属性
    print(f"当前状态: {record.status}")
    record.status = "updated"
    print(f"新状态: {record.status}")
    
    # 查看访问日志
    log = record.get_access_log()
    print(f"\n访问日志: {len(log)}条记录")
    for entry in log[-2:]:
        print(f"  {entry['operation']}: {entry.get('new_value', '读取操作')}")
    
except ValueError as e:
    print(f"验证失败: {e}")

# 尝试无效输入
try:
    record.price = -10  # 这会触发验证错误
except ValueError as e:
    print(f"\n预期的验证错误: {e}")

继承机制与方法解析顺序(MRO)

单继承与方法重写

class DataProcessor:
    """数据处理基类"""
    
    def __init__(self, name):
        super().__init__()
        self.name = name
        self.processed_count = 0
    
    def process(self, data):
        """基础处理方法"""
        self.processed_count += 1
        return f"基础处理: {data}"
    
    def get_stats(self):
        """获取处理统计"""
        return {'name': self.name, 'processed': self.processed_count}
    
    def __str__(self):
        return f"{self.__class__.__name__}({self.name})"

class CSVProcessor(DataProcessor):
    """CSV处理器 - 单继承示例"""
    
    def __init__(self, name, delimiter=','):
        super().__init__(name)  # 调用父类构造函数
        self.delimiter = delimiter
        self.headers = []
    
    def process(self, data):
        """重写父类方法"""
        # 调用父类方法
        base_result = super().process(data)
        
        # 添加CSV特定处理
        if isinstance(data, str):
            fields = data.split(self.delimiter)
            if not self.headers:
                self.headers = fields
                return f"CSV头部设置: {fields}"
            else:
                return f"CSV数据行: {dict(zip(self.headers, fields))}"
        
        return base_result
    
    def get_stats(self):
        """扩展父类方法"""
        stats = super().get_stats()
        stats.update({
            'delimiter': self.delimiter,
            'columns': len(self.headers),
            'headers': self.headers
        })
        return stats

# 演示单继承
print("=== 单继承演示 ===")
csv_proc = CSVProcessor("订单数据处理器")
print(csv_proc.process("order_id,customer,amount"))
print(csv_proc.process("001,张三,1200"))
print(csv_proc.process("002,李四,850"))
print(f"处理统计: {csv_proc.get_stats()}")

多重继承与MRO

class Loggable:
    """日志混入类"""
    
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.log_entries = []
    
    def log(self, message):
        """记录日志"""
        from datetime import datetime
        entry = f"[{datetime.now()}] {message}"
        self.log_entries.append(entry)
        print(f"日志: {message}")
    
    def get_logs(self):
        """获取所有日志"""
        return self.log_entries.copy()

class Cacheable:
    """缓存混入类"""
    
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self._cache = {}
        self._cache_hits = 0
        self._cache_misses = 0
    
    def get_from_cache(self, key):
        """从缓存获取"""
        if key in self._cache:
            self._cache_hits += 1
            return self._cache[key]
        else:
            self._cache_misses += 1
            return None
    
    def set_cache(self, key, value):
        """设置缓存"""
        self._cache[key] = value
    
    def get_cache_stats(self):
        """缓存统计"""
        total = self._cache_hits + self._cache_misses
        hit_rate = self._cache_hits / total if total > 0 else 0
        return {
            'size': len(self._cache),
            'hits': self._cache_hits,
            'misses': self._cache_misses,
            'hit_rate': f"{hit_rate:.2%}"
        }

class EnhancedProcessor(DataProcessor, Loggable, Cacheable):
    """增强处理器 - 多重继承示例"""
    
    def __init__(self, name, cache_size=100):
        # 多重继承时的初始化调用链
        super().__init__(name)
        self.cache_size = cache_size
    
    def process(self, data):
        """带缓存和日志的处理"""
        # 生成缓存键
        cache_key = hash(str(data))
        
        # 尝试从缓存获取
        cached_result = self.get_from_cache(cache_key)
        if cached_result is not None:
            self.log(f"缓存命中: {data}")
            return cached_result
        
        # 缓存未命中,进行处理
        self.log(f"开始处理: {data}")
        result = super().process(data)
        
        # 将结果存入缓存
        if len(self._cache) < self.cache_size:
            self.set_cache(cache_key, result)
            self.log(f"结果已缓存: {cache_key}")
        
        return result
    
    def get_full_stats(self):
        """获取完整统计信息"""
        stats = self.get_stats()
        stats.update({
            'logs_count': len(self.log_entries),
            'cache_stats': self.get_cache_stats()
        })
        return stats

# MRO分析
print("=== 方法解析顺序 (MRO) 分析 ===")
print(f"EnhancedProcessor MRO:")
for i, cls in enumerate(EnhancedProcessor.__mro__):
    print(f"  {i+1}. {cls.__name__}")

# 多重继承演示
print("\n=== 多重继承演示 ===")
enhanced_proc = EnhancedProcessor("高级数据处理器")

# 处理一些数据(会产生日志和缓存)
data_samples = ["样本1", "样本2", "样本1", "样本3", "样本1"]

for data in data_samples:
    result = enhanced_proc.process(data)
    print(f"处理结果: {result}")

print(f"\n完整统计: {enhanced_proc.get_full_stats()}")

抽象基类与接口设计

from abc import ABC, abstractmethod
from typing import Protocol, runtime_checkable

class DataReader(ABC):
    """抽象数据读取器基类"""
    
    @abstractmethod
    def read(self, source):
        """读取数据 - 必须由子类实现"""
        pass
    
    @abstractmethod
    def validate(self, data):
        """验证数据 - 必须由子类实现"""
        pass
    
    # 具体方法可以被继承
    def preprocess(self, data):
        """预处理 - 可选重写"""
        return data
    
    # 模板方法模式
    def load_data(self, source):
        """数据加载流程模板"""
        print(f"开始从 {source} 加载数据")
        raw_data = self.read(source)
        
        print("验证数据格式")
        if not self.validate(raw_data):
            raise ValueError("数据验证失败")
        
        print("预处理数据")
        processed_data = self.preprocess(raw_data)
        
        print("数据加载完成")
        return processed_data

@runtime_checkable
class Serializable(Protocol):
    """序列化协议 - 使用Protocol定义接口"""
    
    def serialize(self) -> str:
        """序列化为字符串"""
        ...
    
    def deserialize(self, data: str) -> 'Serializable':
        """从字符串反序列化"""
        ...

class JSONDataReader(DataReader):
    """JSON数据读取器 - 实现抽象基类"""
    
    def read(self, source):
        """读取JSON数据"""
        import json
        
        if isinstance(source, str) and source.startswith('{'):
            return json.loads(source)
        else:
            # 模拟文件读取
            return {"data": [1, 2, 3], "metadata": {"version": "1.0"}}
    
    def validate(self, data):
        """验证JSON数据"""
        return isinstance(data, dict) and "data" in data
    
    def preprocess(self, data):
        """JSON特定的预处理"""
        # 添加处理时间戳
        data["processed_at"] = __import__('time').time()
        return data

class CSVDataReader(DataReader):
    """CSV数据读取器"""
    
    def read(self, source):
        """读取CSV数据"""
        if isinstance(source, str):
            lines = source.strip().split('\n')
            return [line.split(',') for line in lines]
        return []
    
    def validate(self, data):
        """验证CSV数据"""
        return isinstance(data, list) and len(data) > 0
    
    def preprocess(self, data):
        """CSV预处理:转换为字典格式"""
        if len(data) < 2:
            return data
        
        headers = data[0]
        rows = data[1:]
        return [dict(zip(headers, row)) for row in rows]

# 演示抽象基类
print("=== 抽象基类演示 ===")

# JSON读取器
json_reader = JSONDataReader()
json_data = json_reader.load_data('{"data": [1,2,3], "metadata": {"type": "test"}}')
print(f"JSON数据: {json_data}")

# CSV读取器
csv_reader = CSVDataReader()
csv_data = csv_reader.load_data("name,age,city\nAlice,25,NY\nBob,30,LA")
print(f"CSV数据: {csv_data}")

# 尝试创建抽象类实例(会失败)
try:
    abstract_reader = DataReader()  # TypeError
except TypeError as e:
    print(f"\n无法实例化抽象类: {e}")

多态机制与动态调度

方法多态与动态绑定

from typing import List, Union
import time
from abc import ABC, abstractmethod

class DataTransformer(ABC):
    """数据变换器抽象基类"""
    
    def __init__(self, name: str):
        self.name = name
        self.transform_count = 0
        self.total_time = 0
    
    @abstractmethod
    def transform(self, data):
        """抽象变换方法"""
        pass
    
    def benchmark_transform(self, data):
        """带性能测试的变换"""
        start_time = time.perf_counter()
        result = self.transform(data)
        end_time = time.perf_counter()
        
        self.transform_count += 1
        self.total_time += (end_time - start_time)
        
        return result
    
    def get_stats(self):
        """获取性能统计"""
        avg_time = self.total_time / self.transform_count if self.transform_count > 0 else 0
        return {
            'name': self.name,
            'transforms': self.transform_count,
            'total_time': f"{self.total_time:.6f}s",
            'avg_time': f"{avg_time:.6f}s"
        }

class NumericNormalizer(DataTransformer):
    """数值标准化器"""
    
    def __init__(self, method='z_score'):
        super().__init__(f"数值标准化器({method})")
        self.method = method
        self._stats = None
    
    def transform(self, data: List[float]) -> List[float]:
        """数值标准化变换"""
        if not data:
            return data
        
        if self.method == 'z_score':
            mean_val = sum(data) / len(data)
            variance = sum((x - mean_val) ** 2 for x in data) / len(data)
            std_dev = variance ** 0.5
            
            if std_dev == 0:
                return [0] * len(data)
            
            return [(x - mean_val) / std_dev for x in data]
        
        elif self.method == 'min_max':
            min_val, max_val = min(data), max(data)
            if min_val == max_val:
                return [0] * len(data)
            return [(x - min_val) / (max_val - min_val) for x in data]
        
        return data

class TextTokenizer(DataTransformer):
    """文本标记器"""
    
    def __init__(self, to_lower=True, remove_punctuation=True):
        super().__init__("文本标记器")
        self.to_lower = to_lower
        self.remove_punctuation = remove_punctuation
    
    def transform(self, data: Union[str, List[str]]) -> List[str]:
        """文本标记化变换"""
        import re
        
        if isinstance(data, str):
            data = [data]
        
        results = []
        for text in data:
            if self.to_lower:
                text = text.lower()
            
            if self.remove_punctuation:
                text = re.sub(r'[^\w\s]', '', text)
            
            tokens = text.split()
            results.extend(tokens)
        
        return results

class DataFrameProcessor(DataTransformer):
    """数据框处理器"""
    
    def __init__(self, operations: List[str]):
        super().__init__("数据框处理器")
        self.operations = operations
    
    def transform(self, data: List[dict]) -> List[dict]:
        """数据框变换"""
        if not data:
            return data
        
        result = data.copy()
        
        for op in self.operations:
            if op == 'remove_nulls':
                result = [row for row in result if all(v is not None for v in row.values())]
            elif op == 'add_index':
                for i, row in enumerate(result):
                    row['_index'] = i
            elif op == 'sort_by_first_key':
                if result:
                    first_key = list(result[0].keys())[0]
                    result.sort(key=lambda x: x.get(first_key, 0))
        
        return result

# 多态演示:统一处理不同类型的变换器
def process_data_pipeline(transformers: List[DataTransformer], datasets: List):
    """数据处理管道 - 多态的实际应用"""
    print("=== 数据处理管道启动 ===")
    
    results = []
    
    for i, (transformer, dataset) in enumerate(zip(transformers, datasets)):
        print(f"\n步骤 {i+1}: 使用 {transformer.name} 处理数据")
        print(f"输入数据类型: {type(dataset).__name__}")
        print(f"输入数据长度: {len(dataset) if hasattr(dataset, '__len__') else '未知'}")
        
        # 多态调用:不同变换器的transform方法
        result = transformer.benchmark_transform(dataset)
        
        print(f"输出数据类型: {type(result).__name__}")
        print(f"输出数据长度: {len(result) if hasattr(result, '__len__') else '未知'}")
        print(f"处理统计: {transformer.get_stats()}")
        
        results.append(result)
    
    return results

# 创建不同类型的变换器
transformers = [
    NumericNormalizer('z_score'),
    TextTokenizer(to_lower=True, remove_punctuation=True),
    DataFrameProcessor(['remove_nulls', 'add_index', 'sort_by_first_key']),
    NumericNormalizer('min_max')
]

# 准备对应的测试数据
datasets = [
    [1, 5, 3, 8, 2, 9, 4, 7, 6],  # 数值数据
    ["Hello World!", "Python Programming.", "Data Science?"],  # 文本数据
    [  # 数据框数据
        {'name': 'Alice', 'age': 25, 'score': 85},
        {'name': 'Bob', 'age': None, 'score': 92},
        {'name': 'Charlie', 'age': 30, 'score': 78}
    ],
    [10, 20, 15, 25, 30, 5, 35]  # 另一组数值数据
]

# 运行多态处理管道
results = process_data_pipeline(transformers, datasets)

# 显示最终结果
print("\n=== 处理结果摘要 ===")
for i, result in enumerate(results):
    print(f"步骤 {i+1} 结果: {result[:3]}{'...' if len(result) > 3 else ''}")

运算符重载与协议实现

class Matrix:
    """矩阵类 - 演示运算符重载和协议实现"""
    
    def __init__(self, data):
        """初始化矩阵"""
        if isinstance(data, int):
            # 创建零矩阵
            self.data = [[0] * data for _ in range(data)]
            self.rows = data
            self.cols = data
        else:
            # 从二维列表创建
            self.data = [row[:] for row in data]  # 复制外层列表和各行列表;不递归复制单元格对象
            self.rows = len(data)
            self.cols = len(data[0]) if data else 0
    
    def __str__(self):
        """字符串表示"""
        return '\n'.join([' '.join(f'{cell:6.2f}' for cell in row) for row in self.data])
    
    def __repr__(self):
        """开发者表示"""
        return f"Matrix({self.rows}x{self.cols})"
    
    def __add__(self, other):
        """矩阵加法"""
        if isinstance(other, Matrix):
            if self.rows != other.rows or self.cols != other.cols:
                raise ValueError(f"矩阵维度不匹配: {self.rows}x{self.cols} vs {other.rows}x{other.cols}")
            
            result = Matrix([[0] * self.cols for _ in range(self.rows)])
            for i in range(self.rows):
                for j in range(self.cols):
                    result.data[i][j] = self.data[i][j] + other.data[i][j]
            return result
        
        elif isinstance(other, (int, float)):
            # 标量加法
            result = Matrix(self.data)
            for i in range(self.rows):
                for j in range(self.cols):
                    result.data[i][j] += other
            return result
        
        return NotImplemented
    
    def __radd__(self, other):
        """右加法"""
        return self.__add__(other)
    
    def __mul__(self, other):
        """矩阵乘法或标量乘法"""
        if isinstance(other, Matrix):
            # 矩阵乘法
            if self.cols != other.rows:
                raise ValueError(f"矩阵乘法维度不匹配: {self.rows}x{self.cols} * {other.rows}x{other.cols}")
            
            result = Matrix([[0] * other.cols for _ in range(self.rows)])
            for i in range(self.rows):
                for j in range(other.cols):
                    for k in range(self.cols):
                        result.data[i][j] += self.data[i][k] * other.data[k][j]
            return result
        
        elif isinstance(other, (int, float)):
            # 标量乘法
            result = Matrix(self.data)
            for i in range(self.rows):
                for j in range(self.cols):
                    result.data[i][j] *= other
            return result
        
        return NotImplemented
    
    def __rmul__(self, other):
        """右乘法"""
        return self.__mul__(other)
    
    def __getitem__(self, key):
        """索引访问"""
        if isinstance(key, tuple) and len(key) == 2:
            i, j = key
            return self.data[i][j]
        else:
            return self.data[key]
    
    def __setitem__(self, key, value):
        """索引设置"""
        if isinstance(key, tuple) and len(key) == 2:
            i, j = key
            self.data[i][j] = value
        else:
            self.data[key] = value
    
    def __eq__(self, other):
        """相等比较"""
        if not isinstance(other, Matrix):
            return False
        
        if self.rows != other.rows or self.cols != other.cols:
            return False
        
        for i in range(self.rows):
            for j in range(self.cols):
                if abs(self.data[i][j] - other.data[i][j]) > 1e-9:
                    return False
        
        return True
    
    def transpose(self):
        """转置"""
        result = Matrix([[0] * self.rows for _ in range(self.cols)])
        for i in range(self.rows):
            for j in range(self.cols):
                result.data[j][i] = self.data[i][j]
        return result
    
    def __iter__(self):
        """迭代器协议"""
        for row in self.data:
            yield row

# 演示运算符重载
print("=== 运算符重载演示 ===")

# 创建矩阵
m1 = Matrix([
    [1, 2],
    [3, 4]
])

m2 = Matrix([
    [5, 6], 
    [7, 8]
])

print(f"矩阵 m1:\n{m1}\n")
print(f"矩阵 m2:\n{m2}\n")

# 矩阵运算
print(f"m1 + m2:\n{m1 + m2}\n")
print(f"m1 * m2 (矩阵乘法):\n{m1 * m2}\n")
print(f"m1 * 2 (标量乘法):\n{m1 * 2}\n")
print(f"m1 转置:\n{m1.transpose()}\n")

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

# 迭代
print(f"\n矩阵迭代:")
for i, row in enumerate(m1):
    print(f"第{i}行: {row}")

元类与高级特性

元类机制深入理解

class SingletonMeta(type):
    """单例模式元类"""
    
    _instances = {}
    _lock = __import__('threading').Lock()
    
    def __call__(cls, *args, **kwargs):
        """控制实例创建"""
        if cls not in cls._instances:
            with cls._lock:
                if cls not in cls._instances:
                    instance = super().__call__(*args, **kwargs)
                    cls._instances[cls] = instance
        return cls._instances[cls]
    
    def __new__(mcs, name, bases, attrs):
        """创建类时的定制"""
        # 为所有方法添加日志装饰器
        for key, value in attrs.items():
            if callable(value) and not key.startswith('_'):
                attrs[key] = mcs._add_logging(value, name, key)
        
        return super().__new__(mcs, name, bases, attrs)
    
    @staticmethod
    def _add_logging(func, class_name, method_name):
        """为方法添加日志"""
        def wrapper(*args, **kwargs):
            print(f"调用 {class_name}.{method_name}")
            return func(*args, **kwargs)
        return wrapper

class DatabaseConnection(metaclass=SingletonMeta):
    """数据库连接类 - 使用单例模式"""
    
    def __init__(self, host='localhost', port=5432):
        if hasattr(self, '_initialized'):
            return
        
        self.host = host
        self.port = port
        self.connected = False
        self._initialized = True
        print(f"初始化数据库连接: {host}:{port}")
    
    def connect(self):
        """连接数据库"""
        if not self.connected:
            self.connected = True
            print("数据库连接已建立")
    
    def disconnect(self):
        """断开连接"""
        if self.connected:
            self.connected = False
            print("数据库连接已断开")
    
    def execute_query(self, query):
        """执行查询"""
        if not self.connected:
            raise RuntimeError("数据库未连接")
        print(f"执行查询: {query}")
        return f"查询结果: {query}"

# 演示单例模式
print("=== 单例模式演示 ===")
db1 = DatabaseConnection()
db2 = DatabaseConnection('remote-host', 3306)

print(f"db1 is db2: {db1 is db2}")  # True
print(f"db1.host: {db1.host}, db2.host: {db2.host}")  # 都是localhost

db1.connect()
db1.execute_query("SELECT * FROM users")

设计模式在Python中的应用

from typing import List, Dict, Any
from enum import Enum
import copy

class DataProcessingStrategy(ABC):
    """策略模式:数据处理策略接口"""
    
    @abstractmethod
    def process(self, data: List[Dict[str, Any]]) -> List[Dict[str, Any]]:
        pass

class FilterNullStrategy(DataProcessingStrategy):
    """过滤空值策略"""
    
    def process(self, data):
        return [row for row in data if all(v is not None for v in row.values())]

class SortByKeyStrategy(DataProcessingStrategy):
    """按键排序策略"""
    
    def __init__(self, key: str, reverse=False):
        self.key = key
        self.reverse = reverse
    
    def process(self, data):
        return sorted(data, key=lambda x: x.get(self.key, 0), reverse=self.reverse)

class AggregateStrategy(DataProcessingStrategy):
    """聚合策略"""
    
    def __init__(self, group_by: str, aggregate_key: str, operation='sum'):
        self.group_by = group_by
        self.aggregate_key = aggregate_key
        self.operation = operation
    
    def process(self, data):
        groups = {}
        for row in data:
            key = row.get(self.group_by)
            if key not in groups:
                groups[key] = []
            groups[key].append(row)
        
        result = []
        for group_key, group_data in groups.items():
            if self.operation == 'sum':
                total = sum(row.get(self.aggregate_key, 0) for row in group_data)
            elif self.operation == 'count':
                total = len(group_data)
            elif self.operation == 'avg':
                values = [row.get(self.aggregate_key, 0) for row in group_data]
                total = sum(values) / len(values) if values else 0
            
            result.append({
                self.group_by: group_key,
                f'{self.operation}_{self.aggregate_key}': total
            })
        
        return result

class DataProcessor:
    """数据处理器 - 使用策略模式"""
    
    def __init__(self):
        self._strategies: List[DataProcessingStrategy] = []
    
    def add_strategy(self, strategy: DataProcessingStrategy):
        """添加处理策略"""
        self._strategies.append(strategy)
        return self  # 支持链式调用
    
    def process(self, data: List[Dict[str, Any]]) -> List[Dict[str, Any]]:
        """执行所有策略"""
        result = copy.deepcopy(data)
        
        for i, strategy in enumerate(self._strategies):
            print(f"执行策略 {i+1}: {strategy.__class__.__name__}")
            result = strategy.process(result)
            print(f"处理后数据量: {len(result)}")
        
        return result
    
    def clear_strategies(self):
        """清空策略"""
        self._strategies.clear()

# 工厂模式
class DataProcessorFactory:
    """数据处理器工厂"""
    
    @staticmethod
    def create_etl_processor() -> DataProcessor:
        """创建ETL处理器"""
        return (DataProcessor()
                .add_strategy(FilterNullStrategy())
                .add_strategy(SortByKeyStrategy('timestamp')))
    
    @staticmethod
    def create_analytics_processor(group_key: str) -> DataProcessor:
        """创建分析处理器"""
        return (DataProcessor()
                .add_strategy(FilterNullStrategy())
                .add_strategy(AggregateStrategy(group_key, 'value', 'sum'))
                .add_strategy(SortByKeyStrategy(f'sum_value', reverse=True)))
    
    @staticmethod
    def create_custom_processor(strategies: List[DataProcessingStrategy]) -> DataProcessor:
        """创建自定义处理器"""
        processor = DataProcessor()
        for strategy in strategies:
            processor.add_strategy(strategy)
        return processor

# 演示设计模式
print("\n=== 设计模式演示 ===")

# 测试数据
test_data = [
    {'id': 1, 'category': 'A', 'value': 100, 'timestamp': 1},
    {'id': 2, 'category': 'B', 'value': 200, 'timestamp': 3},
    {'id': 3, 'category': 'A', 'value': None, 'timestamp': 2},
    {'id': 4, 'category': 'B', 'value': 150, 'timestamp': 4},
    {'id': 5, 'category': 'A', 'value': 80, 'timestamp': 5}
]

print("原始数据:")
for row in test_data:
    print(f"  {row}")

# 使用工厂创建处理器
print("\n使用ETL处理器:")
etl_processor = DataProcessorFactory.create_etl_processor()
etl_result = etl_processor.process(test_data)
print(f"ETL结果: {etl_result}")

print("\n使用分析处理器:")
analytics_processor = DataProcessorFactory.create_analytics_processor('category')
analytics_result = analytics_processor.process(test_data)
print(f"分析结果: {analytics_result}")

数据科学中的OOP最佳实践

数据模型设计实例

from typing import Optional, Union, List, Dict
from datetime import datetime
import json

class DataPoint:
    """数据点基类 - 数据科学中的核心概念"""
    
    def __init__(self, value: Union[int, float, str], 
                 timestamp: Optional[datetime] = None,
                 metadata: Optional[Dict] = None):
        self.value = value
        self.timestamp = timestamp or datetime.now()
        self.metadata = metadata or {}
        self._validation_errors = []
    
    def validate(self) -> bool:
        """数据验证"""
        self._validation_errors.clear()
        
        if self.value is None:
            self._validation_errors.append("值不能为空")
        
        if not isinstance(self.timestamp, datetime):
            self._validation_errors.append("时间戳格式错误")
        
        return len(self._validation_errors) == 0
    
    def get_validation_errors(self) -> List[str]:
        return self._validation_errors.copy()
    
    def to_dict(self) -> Dict:
        return {
            'value': self.value,
            'timestamp': self.timestamp.isoformat() if self.timestamp else None,
            'metadata': self.metadata
        }
    
    def __repr__(self):
        return f"DataPoint(value={self.value}, timestamp={self.timestamp})"

class NumericDataPoint(DataPoint):
    """数值型数据点"""
    
    def __init__(self, value: Union[int, float], 
                 unit: Optional[str] = None, **kwargs):
        super().__init__(value, **kwargs)
        self.unit = unit
    
    def validate(self) -> bool:
        """扩展验证"""
        base_valid = super().validate()
        
        if not isinstance(self.value, (int, float)):
            self._validation_errors.append("数值型数据点的值必须是数字")
        
        return base_valid and len(self._validation_errors) == 0
    
    def normalize(self, min_val: float, max_val: float) -> float:
        """数值归一化"""
        if min_val == max_val:
            return 0.0
        return (float(self.value) - min_val) / (max_val - min_val)
    
    def to_dict(self) -> Dict:
        data = super().to_dict()
        data['unit'] = self.unit
        return data

class CategoricalDataPoint(DataPoint):
    """分类型数据点"""
    
    def __init__(self, value: str, categories: Optional[List[str]] = None, **kwargs):
        super().__init__(value, **kwargs)
        self.categories = categories or []
    
    def validate(self) -> bool:
        """分类验证"""
        base_valid = super().validate()
        
        if not isinstance(self.value, str):
            self._validation_errors.append("分类数据点的值必须是字符串")
        
        if self.categories and self.value not in self.categories:
            self._validation_errors.append(f"值 '{self.value}' 不在允许的分类中: {self.categories}")
        
        return base_valid and len(self._validation_errors) == 0
    
    def encode(self, encoding_map: Optional[Dict[str, int]] = None) -> int:
        """分类编码"""
        if encoding_map:
            return encoding_map.get(self.value, -1)
        elif self.categories:
            return self.categories.index(self.value) if self.value in self.categories else -1
        else:
            return hash(self.value) % 1000  # 教学用哈希编码:可能碰撞,且跨进程不保证一致

class DataSet:
    """数据集类 - 管理数据点集合"""
    
    def __init__(self, name: str, description: str = ""):
        self.name = name
        self.description = description
        self.data_points: List[DataPoint] = []
        self.created_at = datetime.now()
        self._dirty = True
        self._cached_stats = None
    
    def add_data_point(self, data_point: DataPoint):
        """添加数据点"""
        if data_point.validate():
            self.data_points.append(data_point)
            self._dirty = True
        else:
            raise ValueError(f"数据点验证失败: {data_point.get_validation_errors()}")
    
    def add_batch(self, data_points: List[DataPoint]):
        """批量添加数据点"""
        valid_points = []
        errors = []
        
        for i, dp in enumerate(data_points):
            if dp.validate():
                valid_points.append(dp)
            else:
                errors.append(f"索引 {i}: {dp.get_validation_errors()}")
        
        if errors:
            print(f"警告: {len(errors)} 个数据点验证失败")
            for error in errors[:5]:  # 只显示前5个错误
                print(f"  {error}")
        
        self.data_points.extend(valid_points)
        self._dirty = True
        
        return len(valid_points), len(errors)
    
    def get_numeric_points(self) -> List[NumericDataPoint]:
        """获取数值型数据点"""
        return [dp for dp in self.data_points if isinstance(dp, NumericDataPoint)]
    
    def get_categorical_points(self) -> List[CategoricalDataPoint]:
        """获取分类型数据点"""
        return [dp for dp in self.data_points if isinstance(dp, CategoricalDataPoint)]
    
    def get_stats(self) -> Dict:
        """获取数据集统计信息(带缓存)"""
        if not self._dirty and self._cached_stats:
            return self._cached_stats
        
        numeric_points = self.get_numeric_points()
        categorical_points = self.get_categorical_points()
        
        stats = {
            'total_points': len(self.data_points),
            'numeric_points': len(numeric_points),
            'categorical_points': len(categorical_points),
            'created_at': self.created_at.isoformat()
        }
        
        if numeric_points:
            values = [dp.value for dp in numeric_points]
            stats['numeric_stats'] = {
                'min': min(values),
                'max': max(values),
                'mean': sum(values) / len(values),
                'count': len(values)
            }
        
        if categorical_points:
            from collections import Counter
            categories = [dp.value for dp in categorical_points]
            stats['categorical_stats'] = {
                'unique_categories': len(set(categories)),
                'most_common': Counter(categories).most_common(5)
            }
        
        self._cached_stats = stats
        self._dirty = False
        return stats
    
    def export_to_json(self, filename: str):
        """导出为JSON文件"""
        data = {
            'name': self.name,
            'description': self.description,
            'stats': self.get_stats(),
            'data_points': [dp.to_dict() for dp in self.data_points]
        }
        
        with open(filename, 'w', encoding='utf-8') as f:
            json.dump(data, f, ensure_ascii=False, indent=2)
        
        print(f"数据集已导出到: {filename}")
    
    def __len__(self):
        return len(self.data_points)
    
    def __iter__(self):
        return iter(self.data_points)
    
    def __str__(self):
        return f"DataSet('{self.name}', {len(self.data_points)} points)"

# 演示数据科学OOP应用
print("=== 数据科学中的OOP应用演示 ===")

# 创建数据集
dataset = DataSet("用户行为分析", "电商平台用户行为数据")

# 添加不同类型的数据点
numeric_data = [
    NumericDataPoint(150.0, unit="元", metadata={"type": "订单金额"}),
    NumericDataPoint(25, unit="岁", metadata={"type": "用户年龄"}),
    NumericDataPoint(3.5, unit="评分", metadata={"type": "商品评分"})
]

categorical_data = [
    CategoricalDataPoint("移动端", ["移动端", "PC端", "平板"], metadata={"type": "访问方式"}),
    CategoricalDataPoint("北京", metadata={"type": "城市"}),
    CategoricalDataPoint("VIP", ["普通", "VIP", "SVIP"], metadata={"type": "用户等级"})
]

# 批量添加数据
valid_count, error_count = dataset.add_batch(numeric_data + categorical_data)
print(f"添加了 {valid_count} 个有效数据点,{error_count} 个错误")

# 获取统计信息
stats = dataset.get_stats()
print(f"\n数据集统计:")
print(f"  总数据点: {stats['total_points']}")
print(f"  数值型: {stats['numeric_points']}")
print(f"  分类型: {stats['categorical_points']}")

if 'numeric_stats' in stats:
    ns = stats['numeric_stats']
    print(f"  数值统计: 最小值={ns['min']}, 最大值={ns['max']}, 平均值={ns['mean']:.2f}")

if 'categorical_stats' in stats:
    cs = stats['categorical_stats']
    print(f"  分类统计: {cs['unique_categories']} 个唯一分类")

# 数据处理示例
print(f"\n数据处理示例:")
numeric_points = dataset.get_numeric_points()
if len(numeric_points) >= 2:
    values = [dp.value for dp in numeric_points]
    min_val, max_val = min(values), max(values)
    
    print(f"归一化结果:")
    for dp in numeric_points[:3]:
        normalized = dp.normalize(min_val, max_val)
        print(f"  {dp.value} -> {normalized:.3f}")

categorical_points = dataset.get_categorical_points()
if categorical_points:
    print(f"\n分类编码示例:")
    for dp in categorical_points[:3]:
        encoded = dp.encode()
        print(f"  '{dp.value}' -> {encoded}")

# 导出数据(注释掉实际文件操作)
# dataset.export_to_json('user_behavior_data.json')
print(f"\n数据集可以导出为JSON格式进行持久化存储")

性能优化与最佳实践

对象创建优化

import sys
from typing import NamedTuple
from dataclasses import dataclass, field
from collections import namedtuple

# 1. 使用 __slots__ 减少内存占用
class Point:
    """普通点类"""
    def __init__(self, x, y):
        self.x = x
        self.y = y

class OptimizedPoint:
    """优化的点类 - 使用 __slots__"""
    __slots__ = ['x', 'y']
    
    def __init__(self, x, y):
        self.x = x
        self.y = y

# 2. 使用 dataclass 简化代码
@dataclass
class DataPoint:
    """数据点类 - 使用 dataclass"""
    x: float
    y: float
    label: str = "default"
    metadata: dict = field(default_factory=dict)
    
    def distance_from_origin(self) -> float:
        return (self.x ** 2 + self.y ** 2) ** 0.5

# 3. 使用 namedtuple 的不可变数据
ImmutablePoint = namedtuple('Point', ['x', 'y'])

class TypedPoint(NamedTuple):
    """类型化的点类"""
    x: float
    y: float
    
    def distance_from_origin(self) -> float:
        return (self.x ** 2 + self.y ** 2) ** 0.5

# 内存使用比较
print("=== 内存使用比较 ===")

# 创建对象并比较内存使用
regular_point = Point(1.0, 2.0)
optimized_point = OptimizedPoint(1.0, 2.0)
data_point = DataPoint(1.0, 2.0)
immutable_point = ImmutablePoint(1.0, 2.0)
typed_point = TypedPoint(1.0, 2.0)

print(f"普通类大小: {sys.getsizeof(regular_point)} + {sys.getsizeof(regular_point.__dict__)} bytes")
print(f"__slots__类大小: {sys.getsizeof(optimized_point)} bytes")
print(f"dataclass大小: {sys.getsizeof(data_point)} + {sys.getsizeof(data_point.__dict__)} bytes")
print(f"namedtuple大小: {sys.getsizeof(immutable_point)} bytes")
print(f"NamedTuple大小: {sys.getsizeof(typed_point)} bytes")

OOP设计原则总结

# SOLID原则在Python中的应用示例

# 1. 单一职责原则 (Single Responsibility Principle)
class DataValidator:
    """只负责数据验证"""
    def validate_email(self, email: str) -> bool:
        return '@' in email and '.' in email
    
    def validate_phone(self, phone: str) -> bool:
        return phone.isdigit() and len(phone) >= 10

class DataFormatter:
    """只负责数据格式化"""
    def format_email(self, email: str) -> str:
        return email.lower().strip()
    
    def format_phone(self, phone: str) -> str:
        return ''.join(filter(str.isdigit, phone))

# 2. 开闭原则 (Open/Closed Principle)
class ReportGenerator(ABC):
    """报告生成器基类 - 对扩展开放,对修改关闭"""
    
    @abstractmethod
    def generate(self, data) -> str:
        pass

class PDFReportGenerator(ReportGenerator):
    """PDF报告生成器 - 扩展而不修改基类"""
    def generate(self, data) -> str:
        return f"PDF报告: {data}"

class ExcelReportGenerator(ReportGenerator):
    """Excel报告生成器 - 新功能通过扩展实现"""
    def generate(self, data) -> str:
        return f"Excel报告: {data}"

# 3. 里氏替换原则 (Liskov Substitution Principle)
class Bird(ABC):
    @abstractmethod
    def move(self) -> str:
        pass

class FlyingBird(Bird):
    def move(self) -> str:
        return "飞行"
    
    def fly(self) -> str:
        return "在天空中飞行"

class WalkingBird(Bird):
    def move(self) -> str:
        return "行走"
    
    def walk(self) -> str:
        return "在地面上行走"

# 4. 接口隔离原则 (Interface Segregation Principle)
class Readable(Protocol):
    def read(self) -> str: ...

class Writable(Protocol):
    def write(self, data: str) -> None: ...

class Executable(Protocol):
    def execute(self) -> None: ...

# 5. 依赖倒置原则 (Dependency Inversion Principle)
class DataStorage(ABC):
    """抽象存储接口"""
    @abstractmethod
    def save(self, data: str) -> bool:
        pass

class FileStorage(DataStorage):
    def save(self, data: str) -> bool:
        print(f"保存到文件: {data}")
        return True

class DatabaseStorage(DataStorage):
    def save(self, data: str) -> bool:
        print(f"保存到数据库: {data}")
        return True

class DataService:
    """依赖抽象而不是具体实现"""
    def __init__(self, storage: DataStorage):
        self.storage = storage
    
    def process_data(self, data: str):
        processed = f"处理后的{data}"
        return self.storage.save(processed)

print("\n=== SOLID原则应用演示 ===")

# 依赖注入示例
file_service = DataService(FileStorage())
db_service = DataService(DatabaseStorage())

file_service.process_data("用户数据")
db_service.process_data("订单数据")

print("\n=== 最佳实践总结 ===")
print("1. 使用 __slots__ 优化内存使用")
print("2. 合理使用 dataclass 和 NamedTuple")
print("3. 遵循 SOLID 设计原则")
print("4. 优先组合而非继承")
print("5. 使用类型提示提高代码可读性")
print("6. 实现适当的特殊方法(__str__, __repr__ 等)")
print("7. 使用属性(property)控制属性访问")
print("8. 合理使用抽象基类定义接口")

知识连接与学习路径

info 学习路径规划

前置知识:Python函数编程
后续学习:NumPy数值计算
相关主题:Pandas数据结构 - 大量使用OOP设计

tip 数据科学中的应用

  • 机器学习框架:sklearn、tensorflow等都是OOP设计
  • 数据处理工具:pandas、numpy的核心都是类和对象
  • 可视化库:matplotlib、plotly使用对象管理图表
  • 数据管道:ETL流程的模块化设计

example 实际应用场景

  • 数据模型设计:用类表示业务实体和数据结构
  • 算法封装:将复杂算法包装成可重用的类
  • 系统架构:微服务和API的面向对象设计
  • 工具开发:创建专业的数据分析工具包

文档信息

  • 创建日期:2024-06-29
  • 最后更新:2024-12-21
  • 技术深度:中级到高级
  • 预估学习时间:90-120分钟

关键标签
#Python #OOP #面向对象 #类与对象 #封装 #继承 #多态 #元类 #设计模式 #数据科学 #性能优化