Python如何实现以其他枚举为键的ErrorMap错误映射枚举
实现方案
按照单一职责原则拆分各模块实现,可完全匹配预期调用模式,且支持多领域错误枚举扩展:
1. 基础依赖与异常基类
首先定义公共依赖、所有领域异常的基类,以及具体业务异常:
from enum import Enum from typing import Generic, TypeVar, Optional, Type from pydantic import BaseModel Dto = TypeVar("Dto", bound=BaseModel) # 所有自定义领域异常的公共基类,方便上层统一捕获 class BaseDomainException(Exception): def __init__(self, message: str, **kwargs): self.message = message super().__init__(message) # 示例具体异常实现 class GenericErrorException(BaseDomainException): pass class CartNotFoundException(BaseDomainException): pass class OutOfStockException(BaseDomainException): pass
2. 领域错误枚举定义
枚举类仅负责定义错误slug标识,不掺杂任何映射逻辑:
class DomainErrorEnum(Enum): GENERIC_ERROR = "GENERIC_ERROR" NOT_FOUND = "NOT_FOUND" OUT_OF_STOCK = "OUT_OF_STOCK"
3. ErrorMap映射实现
不要强行继承Enum(多枚举场景下Enum多继承存在语法限制,且无法匹配预期的索引调用写法),通过重写类级索引方法实现完全一致的调用体验,同时支持后续扩展注册多业务域的错误映射:
class ErrorMap: _MAPPING: dict[Enum, Type[BaseDomainException]] = { DomainErrorEnum.GENERIC_ERROR: GenericErrorException, DomainErrorEnum.NOT_FOUND: CartNotFoundException, DomainErrorEnum.OUT_OF_STOCK: OutOfStockException } def __class_getitem__(cls, error_code: Enum) -> Type[BaseDomainException]: # 未配置映射的错误统一返回通用异常 return cls._MAPPING.get(error_code, GenericErrorException) @classmethod def register(cls, error_code: Enum, exception_cls: Type[BaseDomainException]): """扩展方法:注册其他业务域的错误-异常映射""" cls._MAPPING[error_code] = exception_cls
4. 修正Result与BaseError模型
修复原定义中的字段声明错误,补充成功状态判断、异常实例化逻辑:
class BaseError(BaseModel): error_code: DomainErrorEnum message: str def raise_error(self): # 实例化对应异常,传入错误上下文信息 raise ErrorMap[self.error_code](self.message) class Result(BaseModel, Generic[Dto]): error: Optional[BaseError] = None data: Optional[Dto] = None @property def is_success(self) -> bool: return self.error is None
调用示例
完全兼容给出的业务场景写法:
# 领域层用例 def specific_use_case(): # 适配器层返回Result结构,不直接抛异常 result_search: Result[ProductDto] = adapter.search_product() if result_search.is_success: data: ProductDto = result_search.data # 纯业务逻辑层可直接抛异常,不依赖Result包装 business_rules_method(data) return entity # 自动抛出对应类型的领域异常 result_search.error.raise_error()
后续新增其他业务域的错误枚举时,只需要定义对应枚举和异常类,调用ErrorMap.register()注册映射即可,不需要修改核心逻辑。
内容的提问来源于stack exchange,提问作者Tâmer Cuba
相关产品推荐
相关产品推荐

