CodeWalk

Python描述符与元类结合:声明式API框架设计

作者:我还是少年 · 2026-05-30 12:55

结合描述符和元类设计一个声明式API框架。要求:1)使用描述符定义API端点(如GET('/users'));2)使用元类自动收集端点注册到路由表;3)支持参数验证和文档生成。说明为什么描述符+元类的组合适合声明式编程范式,并给出一个简化的Web框架控制器示例。

回答

我还是少年

import inspect

class Route:
    def __init__(self, path, methods=['GET']):
        self.path = path
        self.methods = methods
        self.handler = None
    
    def __set_name__(self, owner, name):
        self.name = name
    
    def __get__(self, obj, objtype=None):
        if obj is None:
            return self
        return self.handler.__get__(obj, objtype)
    
    def __set__(self, obj, value):
        self.handler = value

class ControllerMeta(type):
    def __new__(mcs, name, bases, namespace):
        routes = {}
        for attr_name, attr_val in namespace.items():
            if isinstance(attr_val, Route):
                routes[attr_val.path] = {
                    'handler': attr_name,
                    'methods': attr_val.methods
                }
        namespace['_routes'] = routes
        return super().__new__(mcs, name, bases, namespace)

class Controller(metaclass=ControllerMeta):
    @classmethod
    def register(cls, app):
        for path, info in cls._routes.items():
            handler = getattr(cls, info['handler'])
            app.add_route(path, handler, methods=info['methods'])

# 使用示例
class UserController(Controller):
    list_users = Route('/users')
    
    def list_users(self, request):
        return {'users': ['Alice', 'Bob']}
    
    get_user = Route('/users/{id}')
    def get_user(self, request, id):
        return {'id': id, 'name': 'Alice'}

app = App()
UserController.register(app)

优势

  1. 声明式——关注"是什么"而非"怎么做"
  2. 描述符负责属性行为(动态绑定handler)
  3. 元类在类创建阶段收集元数据(路由表、文档)
  4. 用户代码简洁直观,框架逻辑集中封装