Python案例如何封装复用

wen python案例 50

本文目录导读:

Python案例如何封装复用

  1. 函数封装(基础复用)
  2. 类封装(面向对象复用)
  3. 装饰器封装(功能增强复用)
  4. 模块封装(项目级复用)
  5. 配置文件封装(参数复用)
  6. 最佳实践建议

我来详细讲解Python案例封装复用的多种方法和最佳实践。

函数封装(基础复用)

# 原始案例:计算圆形面积
def calculate_circle_area(radius):
    """计算圆形面积"""
    import math
    return math.pi * radius ** 2
# 封装复用
def calculate_area(shape, *args):
    """
    通用面积计算函数
    :param shape: 形状类型 circle/rectangle/triangle
    :param args: 对应参数
    """
    import math
    if shape == 'circle':
        radius = args[0]
        return math.pi * radius ** 2
    elif shape == 'rectangle':
        length, width = args
        return length * width
    elif shape == 'triangle':
        base, height = args
        return 0.5 * base * height
    else:
        raise ValueError(f"不支持的形状: {shape}")
# 使用示例
print(calculate_area('circle', 5))  # 圆形
print(calculate_area('rectangle', 4, 6))  # 矩形

类封装(面向对象复用)

class DataProcessor:
    """数据处理类封装"""
    def __init__(self, data):
        self.data = data
        self.processed_data = None
    def clean_data(self):
        """数据清洗"""
        self.processed_data = [
            item.strip() for item in self.data 
            if item and not item.isspace()
        ]
        return self
    def transform_data(self, func):
        """数据转换"""
        if self.processed_data is None:
            self.clean_data()
        self.processed_data = [func(item) for item in self.processed_data]
        return self
    def filter_data(self, condition):
        """数据过滤"""
        if self.processed_data is None:
            self.clean_data()
        self.processed_data = [
            item for item in self.processed_data 
            if condition(item)
        ]
        return self
    def get_result(self):
        """获取结果"""
        return self.processed_data
# 使用示例
processor = DataProcessor(["  apple ", "banana", "", "  cherry  "])
result = (processor
          .clean_data()
          .transform_data(str.upper)
          .filter_data(lambda x: len(x) > 5)
          .get_result())
print(result)  # ['BANANA', 'CHERRY']

装饰器封装(功能增强复用)

import time
from functools import wraps
def timer_decorator(func):
    """计时装饰器"""
    @wraps(func)
    def wrapper(*args, **kwargs):
        start = time.time()
        result = func(*args, **kwargs)
        end = time.time()
        print(f"{func.__name__} 执行时间: {end - start:.4f}秒")
        return result
    return wrapper
def cache_decorator(func):
    """缓存装饰器"""
    cache = {}
    @wraps(func)
    def wrapper(*args, **kwargs):
        # 创建缓存键
        key = str(args) + str(sorted(kwargs.items()))
        if key not in cache:
            cache[key] = func(*args, **kwargs)
        return cache[key]
    return wrapper
# 使用示例
@timer_decorator
@cache_decorator
def fibonacci(n):
    """斐波那契数列"""
    if n <= 1:
        return n
    return fibonacci(n-1) + fibonacci(n-2)
print(fibonacci(30))  # 第一次计算并缓存
print(fibonacci(30))  # 从缓存读取

模块封装(项目级复用)

文件结构

project/
├── utils/
│   ├── __init__.py
│   ├── data_handler.py
│   └── validators.py
├── core/
│   ├── __init__.py
│   └── calculator.py
└── main.py

utils/validators.py

def validate_email(email):
    """验证邮箱格式"""
    import re
    pattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'
    return bool(re.match(pattern, email))
def validate_phone(phone):
    """验证手机号"""
    import re
    pattern = r'^1[3-9]\d{9}$'
    return bool(re.match(pattern, phone))

core/calculator.py

class StatisticsCalculator:
    """统计计算器"""
    @staticmethod
    def mean(data):
        """计算平均值"""
        return sum(data) / len(data) if data else 0
    @staticmethod
    def median(data):
        """计算中位数"""
        sorted_data = sorted(data)
        n = len(sorted_data)
        if n % 2 == 0:
            return (sorted_data[n//2 - 1] + sorted_data[n//2]) / 2
        return sorted_data[n//2]
    @staticmethod
    def standard_deviation(data):
        """计算标准差"""
        import math
        mean = StatisticsCalculator.mean(data)
        variance = sum((x - mean) ** 2 for x in data) / len(data)
        return math.sqrt(variance)

main.py

from utils.validators import validate_email, validate_phone
from core.calculator import StatisticsCalculator
# 使用工具函数
emails = ["test@example.com", "invalid-email"]
valid_emails = [email for email in emails if validate_email(email)]
print(f"有效邮箱: {valid_emails}")
# 使用统计计算器
data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
calc = StatisticsCalculator()
print(f"平均值: {calc.mean(data)}")
print(f"中位数: {calc.median(data)}")
print(f"标准差: {calc.standard_deviation(data):.2f}")

配置文件封装(参数复用)

config/settings.py

import json
import os
from typing import Any, Dict
class Config:
    """配置管理类"""
    _instance = None
    def __new__(cls):
        if cls._instance is None:
            cls._instance = super().__new__(cls)
            cls._instance._config = {}
        return cls._instance
    def load_from_file(self, filepath: str):
        """从文件加载配置"""
        if not os.path.exists(filepath):
            raise FileNotFoundError(f"配置文件不存在: {filepath}")
        with open(filepath, 'r', encoding='utf-8') as f:
            if filepath.endswith('.json'):
                self._config = json.load(f)
            elif filepath.endswith('.toml'):
                import tomli
                self._config = tomli.load(f)
        return self
    def get(self, key: str, default: Any = None) -> Any:
        """获取配置值"""
        keys = key.split('.')
        value = self._config
        for k in keys:
            if isinstance(value, dict):
                value = value.get(k, default)
            else:
                return default
        return value
    def set(self, key: str, value: Any):
        """设置配置值"""
        keys = key.split('.')
        config = self._config
        for k in keys[:-1]:
            if k not in config:
                config[k] = {}
            config = config[k]
        config[keys[-1]] = value
# 使用示例
config = Config()
config.load_from_file('config/app.json')
db_host = config.get('database.host', 'localhost')
db_port = config.get('database.port', 5432)

最佳实践建议

封装原则

# 1. 单一职责原则
class UserManager:
    """用户管理类 - 只负责用户相关操作"""
    def create_user(self, username, email):
        pass
    def delete_user(self, user_id):
        pass
    def update_user(self, user_id, data):
        pass
# 2. 接口简单易用
class EmailSender:
    """邮件发送器 - 简单接口"""
    def send(self, to, subject, body):
        """简化的发送方法"""
        return self._send_email(to, subject, body)
    def _send_email(self, to, subject, body):
        """实际发送逻辑"""
        # 实现细节
        pass
# 3. 提供默认参数
def process_data(data, format='json', encoding='utf-8'):
    """数据处理函数,提供默认参数"""
    if format == 'json':
        import json
        return json.dumps(data, ensure_ascii=False)
    elif format == 'csv':
        import csv
        # 处理逻辑
        pass

文档和测试

def calculate_discount(price: float, discount: float = 0.1) -> float:
    """
    计算折扣价格
    Args:
        price: 原价
        discount: 折扣率,默认0.1(10%)
    Returns:
        折扣后的价格
    Raises:
        ValueError: 当折扣率不在0-1之间时
    """
    if not 0 <= discount <= 1:
        raise ValueError(f"折扣率必须在0-1之间,当前为{discount}")
    return price * (1 - discount)
# 测试用例
def test_calculate_discount():
    assert calculate_discount(100) == 90
    assert calculate_discount(100, 0.2) == 80
    assert calculate_discount(0) == 0
    import pytest
    with pytest.raises(ValueError):
        calculate_discount(100, 1.5)

这些封装方法可以让你在项目中高效复用代码,减少重复工作,提高开发效率,选择合适的封装方式取决于具体需求和场景。

抱歉,评论功能暂时关闭!