《边学边练:Python 从零开始:无人机直流电机测试数据采集与可视化全攻略 8》

11. 进阶学习路径

11.1 Python 编程进阶

11.1.1 高级 Python 特性

装饰器(Decorators)
装饰器是 Python 中一种强大的代码重用机制,允许在不修改原函数代码的情况下扩展函数功能。在电机测试系统中,可以用于日志记录、性能计时、权限验证等。

代码示例:实用装饰器

python

运行

import time
import logging
from functools import wraps

# 配置日志
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
logger = logging.getLogger(__name__)

def log_function_call(func):
    """记录函数调用的装饰器"""
    @wraps(func)
    def wrapper(*args, **kwargs):
        logger.info(f"调用函数: {func.__name__}, 参数: {args}, {kwargs}")
        try:
            result = func(*args, **kwargs)
            logger.info(f"函数 {func.__name__} 执行成功")
            return result
        except Exception as e:
            logger.error(f"函数 {func.__name__} 执行失败: {str(e)}", exc_info=True)
            raise  # 重新抛出异常,让调用者处理
    return wrapper

def measure_execution_time(func):
    """测量函数执行时间的装饰器"""
    @wraps(func)
    def wrapper(*args, **kwargs):
        start_time = time.time()
        result = func(*args, **kwargs)
        end_time = time.time()
        logger.info(f"函数 {func.__name__} 执行时间: {end_time - start_time:.4f} 秒")
        return result
    return wrapper

def retry_on_failure(max_retries=3, delay_seconds=1):
    """失败时重试的装饰器"""
    def decorator(func):
        @wraps(func)
        def wrapper(*args, **kwargs):
            retries = 0
            while retries < max_retries:
                try:
                    return func(*args, **kwargs)
                except Exception as e:
                    retries += 1
                    if retries < max_retries:
                        logger.warning(f"函数 {func.__name__} 执行失败,将在 {delay_seconds} 秒后重试({retries}/{max_retries})")
                        time.sleep(delay_seconds)
                    else:
                        logger.error(f"函数 {func.__name__} 达到最大重试次数 {max_retries},执行失败")
                        raise  # 达到最大重试次数,抛出异常
        return wrapper
    return decorator

# 在电机测试系统中的应用示例
@log_function_call
@measure_execution_time
def process_motor_data(data):
    """处理电机数据"""
    # 处理逻辑
    pass

@log_function_call
@retry_on_failure(max_retries=5, delay_seconds=2)
def send_data_over_network(data):
    """通过网络发送数据"""
    # 发送逻辑
    pass

上下文管理器(Context Managers)
上下文管理器用于管理资源,确保资源在使用后被正确释放,如文件、网络连接、数据库连接等。在电机测试系统中,可用于串口连接、文件操作等场景。

代码示例:自定义上下文管理器

python

运行

import serial
import time

class SerialConnection:
    """串口连接上下文管理器"""
    def __init__(self, port='COM3', baudrate=115200, timeout=1):
        self.port = port
        self.baudrate = baudrate
        self.timeout = timeout
        self.serial = None
    
    def __enter__(self):
        """进入上下文,建立连接"""
        try:
            self.serial = serial.Serial(
                port=self.port,
                baudrate=self.baudrate,
                timeout=self.timeout
            )
            print(f"成功打开串口: {self.port}")
            return self.serial
        except Exception as e:
            print(f"打开串口失败: {e}")
            raise  # 传播异常
    
    def __exit__(self, exc_type, exc_val, exc_tb):
        """退出上下文,关闭连接"""
        if self.serial and self.serial.is_open:
            self.serial.close()
            print(f"已关闭串口: {self.port}")
        
        # 处理异常
        if exc_type:
            print(f"串口操作发生异常: {exc_val}")
            # 返回False表示异常需要继续传播,True表示异常已处理
            return False

# 使用示例
def read_serial_data(port='COM3', baudrate=115200):
    with SerialConnection(port, baudrate) as ser:
        # 在with块中使用串口
        while True:
            data = ser.readline().decode('utf-8').strip()
            if data:
                print(f"收到数据: {data}")
            time.sleep(0.1)

# 自定义文件处理上下文管理器
class DataFileHandler:
    """数据文件处理上下文管理器"""
    def __init__(self, file_path, mode='r'):
        self.file_path = file_path
        self.mode = mode
        self.file = None
    
    def __enter__(self):
        """打开文件"""
        self.file = open(self.file_path, self.mode)
        return self.file
    
    def __exit__(self, exc_type, exc_val, exc_tb):
        """关闭文件"""
        if self.file:
            self.file.close()
        
        # 处理异常
        if exc_type:
            print(f"文件操作错误: {exc_val}")
            return False

# 使用示例
with DataFileHandler('motor_data.csv', 'w') as f:
    f.write('timestamp,current,encoder\n')
    # 写入数据...

生成器与迭代器(Generators and Iterators)
生成器是一种特殊的迭代器,能够高效处理大量数据或无限序列,特别适合处理电机测试系统中的数据流。

代码示例:生成器应用

python

运行

import time
import random

def motor_data_generator(motor_id, duration=None):
    """电机数据生成器,模拟实时数据采集"""
    start_time = time.time()
    
    while True:
        # 如果指定了持续时间,检查是否超时
        if duration and time.time() - start_time > duration:
            break
            
        # 生成模拟数据
        timestamp = time.time()
        current = random.uniform(0.5, 3.5)  # 电流值在0.5-3.5A之间
        encoder = random.uniform(0, 1000)   # 编码器值
        
        # 随机产生异常值
        if random.random() < 0.05:  # 5%的概率产生异常值
            current = random.uniform(4.0, 6.0)
        
        yield {
            'motor_id': motor_id,
            'timestamp': timestamp,
            'current': current,
            'encoder': encoder,
            'status': 'running' if current < 4.0 else 'error'
        }
        
        # 模拟采样间隔
        time.sleep(0.1)

def data_processor(data_generator, threshold=4.0):
    """数据处理器,过滤异常值"""
    for data in data_generator:
        if data['current'] > threshold:
            # 处理异常数据
            yield {**data, 'is_anomaly': True}
        else:
            yield {** data, 'is_anomaly': False}

# 使用示例
if __name__ == "__main__":
    # 创建电机数据生成器,持续10秒
    generator = motor_data_generator(motor_id=1, duration=10)
    
    # 创建数据处理器
    processor = data_processor(generator)
    
    # 处理数据
    for processed_data in processor:
        if processed_data['is_anomaly']:
            print(f"异常数据: {processed_data}")
        else:
            # 正常数据可以写入文件或数据库
            pass
11.1.2 面向对象编程高级特性

类装饰器与元类
类装饰器和元类是 Python 中用于修改类行为的高级特性,可以实现自动日志记录、属性验证、注册机制等功能。

代码示例:类装饰器与元类

python

运行

def add_logging(cls):
    """为类添加日志功能的装饰器"""
    # 遍历类的所有方法
    for name, method in cls.__dict__.items():
        # 只处理实例方法
        if callable(method) and not name.startswith('__'):
            # 为方法添加日志功能
            def logged_method(method):
                def wrapper(self, *args, **kwargs):
                    print(f"调用 {cls.__name__}.{method.__name__}, 参数: {args}, {kwargs}")
                    try:
                        result = method(self, *args, **kwargs)
                        print(f"{cls.__name__}.{method.__name__} 执行成功")
                        return result
                    except Exception as e:
                        print(f"{cls.__name__}.{method.__name__} 执行失败: {e}")
                        raise
                return wrapper
            setattr(cls, name, logged_method(method))
    return cls

# 使用类装饰器
@add_logging
class MotorController:
    """电机控制器类"""
    def __init__(self, motor_id):
        self.motor_id = motor_id
        self.current = 0.0
        self.running = False
    
    def start(self):
        self.running = True
        print(f"电机 {self.motor_id} 已启动")
    
    def stop(self):
        self.running = False
        print(f"电机 {self.motor_id} 已停止")
    
    def set_current(self, current):
        if current < 0:
            raise ValueError("电流不能为负值")
        self.current = current
        return self.current

# 元类示例
class ValidationMeta(type):
    """用于属性验证的元类"""
    def __new__(cls, name, bases, namespace):
        # 遍历类属性
        for attr_name, attr_value in namespace.items():
            # 如果是属性且有验证器
            if isinstance(attr_value, property) and hasattr(attr_value, 'validator'):
                # 包装属性的getter方法,添加验证
                def make_validated_property(prop):
                    def getter(self):
                        return prop.fget(self)
                    
                    def setter(self, value):
                        # 调用验证器
                        if prop.validator(value):
                            prop.fset(self, value)
                        else:
                            raise ValueError(f"属性 {attr_name} 的值 {value} 无效")
                    
                    return property(getter, setter)
                
                # 替换原始属性
                namespace[attr_name] = make_validated_property(attr_value)
        
        return super().__new__(cls, name, bases, namespace)

# 使用元类
class MotorData(metaclass=ValidationMeta):
    """电机数据类,使用元类进行属性验证"""
    def __init__(self):
        self._current = 0.0
        self._temperature = 25.0
    
    @property
    def current(self):
        return self._current
    
    @current.setter
    def current(self, value):
        self._current = value
    
    # 添加验证器:电流必须在0-10A之间
    current.validator = lambda x: 0 <= x <= 10
    
    @property
    def temperature(self):
        return self._temperature
    
    @temperature.setter
    def temperature(self, value):
        self._temperature = value
    
    # 添加验证器:温度必须在-40-100摄氏度之间
    temperature.validator = lambda x: -40 <= x <= 100

# 使用示例
if __name__ == "__main__":
    # 测试类装饰器
    motor = MotorController(1)
    motor.start()
    motor.set_current(2.5)
    motor.stop()
    
    # 测试元类验证
    data = MotorData()
    data.current = 5.0  # 有效
    print(f"电流: {data.current}")
    
    try:
        data.current = 11.0  # 无效值,会触发验证错误
    except ValueError as e:
        print(f"设置电流失败: {e}")
    
    data.temperature = 30.0  # 有效
    print(f"温度: {data.temperature}")
    
    try:
        data.temperature = 110.0  # 无效值
    except ValueError as e:
        print(f"设置温度失败: {e}")

抽象基类(Abstract Base Classes)
抽象基类用于定义接口,确保子类实现特定的方法,提高代码的一致性和可维护性。

代码示例:抽象基类应用

python

运行

from abc import ABC, abstractmethod
import time

class MotorInterface(ABC):
    """电机控制抽象基类,定义接口"""
    
    @abstractmethod
    def start(self):
        """启动电机"""
        pass
    
    @abstractmethod
    def stop(self):
        """停止电机"""
        pass
    
    @abstractmethod
    def set_speed(self, speed):
        """设置电机速度"""
        pass
    
    @abstractmethod
    def get_status(self):
        """获取电机状态"""
        pass
    
    @abstractmethod
    def get_sensor_data(self):
        """获取传感器数据"""
        pass

class DC Motor(MotorInterface):
    """直流电机实现类"""
    def __init__(self, motor_id):
        self.motor_id = motor_id
        self.running = False
        self.speed = 0
        self.current = 0.0
        self.temperature = 25.0
    
   
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值