[深度]Python高级特性精讲:装饰器、上下文管理器与元类实战

阿里云推广

Python高级特性深度精讲

Python之所以强大,很大程度上来自这几个高级特性:装饰器、上下文管理器、元类。它们是框架代码和优雅架构的基础,也是从初级到中级的分水岭。

一、装饰器:函数的函数

装饰器的本质是高阶函数,接收一个函数,返回一个新函数。理解它需要先理解Python函数是一等公民。

import time, functools

# 生产级装饰器模板
def retry(max_times=3, delay=1, exceptions=(Exception,)):
    """自动重试装饰器"""
    def decorator(func):
        @functools.wraps(func)  # 保留原函数的__name__,__doc__等
        def wrapper(*args, **kwargs):
            last_exc = None
            for attempt in range(1, max_times + 1):
                try:
                    return func(*args, **kwargs)
                except exceptions as e:
                    last_exc = e
                    if attempt < max_times:
                        print(f'{func.__name__} 第{attempt}次失败: {e}, {delay}秒后重试...')
                        time.sleep(delay)
            raise last_exc
        return wrapper
    return decorator

@retry(max_times=3, delay=2, exceptions=(ConnectionError, TimeoutError))
def call_external_api(url):
    import requests
    return requests.get(url, timeout=5).json()

二、上下文管理器:优雅处理资源

from contextlib import contextmanager
import sqlite3

# 方式1: 实现__enter__和__exit__
class DatabaseConnection:
    def __init__(self, db_path):
        self.db_path = db_path
        self.conn = None

    def __enter__(self):
        self.conn = sqlite3.connect(self.db_path)
        return self.conn

    def __exit__(self, exc_type, exc_val, exc_tb):
        if exc_type:  # 有异常时回滚
            self.conn.rollback()
        else:
            self.conn.commit()
        self.conn.close()
        return False  # 不吞异常

# 方式2: @contextmanager更简洁
@contextmanager
def timer(name):
    start = time.time()
    yield  # yield之前=__enter__, yield之后=__exit__
    elapsed = time.time() - start
    print(f'{name} 耗时: {elapsed:.3f}s')

# 使用
with DatabaseConnection('app.db') as conn:
    conn.execute('INSERT INTO logs VALUES (?)', ('test',))

with timer('数据处理'):
    time.sleep(0.5)

三、元类:控制类的创建过程

# 元类的使用场景: ORM框架、API自动注册、单例模式

# 用元类实现单例
class SingletonMeta(type):
    _instances = {}

    def __call__(cls, *args, **kwargs):
        if cls not in cls._instances:
            cls._instances[cls] = super().__call__(*args, **kwargs)
        return cls._instances[cls]

class DatabasePool(metaclass=SingletonMeta):
    def __init__(self):
        self.pool = []
        print('初始化连接池')

p1 = DatabasePool()  # 打印: 初始化连接池
p2 = DatabasePool()  # 不再打印
print(p1 is p2)      # True

# 更实用:用元类自动注册子类
class HandlerRegistry(type):
    handlers = {}
    def __init__(cls, name, bases, attrs):
        super().__init__(name, bases, attrs)
        if hasattr(cls, 'event_type'):
            HandlerRegistry.handlers[cls.event_type] = cls

class BaseHandler(metaclass=HandlerRegistry): pass

class LoginHandler(BaseHandler):
    event_type = 'login'
    def handle(self, event): print(f'处理登录事件: {event}')

# 自动查找handler
event = {'type': 'login', 'user': 'alice'}
handler_cls = HandlerRegistry.handlers[event['type']]
handler_cls().handle(event)

四、描述符:property的底层原理

# property的本质是描述符协议
class ValidatedAge:
    """年龄描述符,自动验证范围"""
    def __set_name__(self, owner, name):
        self.name = name

    def __get__(self, obj, objtype=None):
        if obj is None:
            return self
        return obj.__dict__.get(self.name)

    def __set__(self, obj, value):
        if not isinstance(value, int):
            raise TypeError('年龄必须是整数')
        if not 0 <= value <= 150:
            raise ValueError(f'年龄范围错误: {value}')
        obj.__dict__[self.name] = value

class Person:
    age = ValidatedAge()

p = Person()
p.age = 25   # OK
p.age = -1   # ValueError!

总结:这三个特性的核心思想都是元编程——用代码控制代码的行为。装饰器在运行时修改函数行为,上下文管理器保证资源正确释放,元类控制类的创建。掌握它们,你能写出更优雅、更有表达力的Python代码。

发表评论