You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为存储编译后正则的Enum实现静态类型与便捷调用?

问题

我在编写AST相关代码时,需要将多个编译好的正则表达式统一存储复用,用Enum管理这些正则模式既简洁又可读:

import re
import enum

class Patterns(enum.Enum):
    """
    用于读取xyz文件中类型声明的正则模式
    """
    Simple: re.Pattern = re.compile(r"([\w_]+)\s*[\|;]")
    Complex: re.Pattern = re.compile(r"([\w_]+)\s*:\s*([\w_]+)")

但直接调用Enum成员的正则方法会失败:

text = "{ a : alpha; b : bravo; c : charlie}"
pattern = Patterns.Complex
print(dict(pattern.findall(text)))  # 报错:'Patterns' object has no attribute 'findall'

原因是pattern是Enum成员类型,而非re.Pattern实例,没有对应的正则方法。对于int、str这类类型,可以通过同时子类化Enum和目标类型解决,但re.Pattern被标记为typing.Final,不应该子类化(强行子类化会触发静态类型检查报错)。目前只能通过提取.value属性调用方法,但这种方式不够便捷,希望找到更简洁的实现方案。


解决方案1:给Enum类添加属性转发方法

在Enum类中定义__getattr__方法,当访问Enum成员不存在的属性时,自动转发到其value对象上:

import re
import enum

class Patterns(enum.Enum):
    """
    用于读取xyz文件中类型声明的正则模式
    """
    Simple: re.Pattern = re.compile(r"([\w_]+)\s*[\|;]")
    Complex: re.Pattern = re.compile(r"([\w_]+)\s*:\s*([\w_]+)")

    def __getattr__(self, name):
        # 将属性访问转发到对应的re.Pattern实例
        return getattr(self.value, name)

现在可以直接调用Enum成员的正则方法:

text = "{ a : alpha; b : bravo; c : charlie}"
pattern = Patterns.Complex
print(dict(pattern.findall(text)))  # 输出: {'a': 'alpha', 'b': 'bravo', 'c': 'charlie'}

这种方式无需修改调用代码,静态类型检查器可能需要额外的类型提示(比如typing.cast),但运行时完全正常。

解决方案2:封装通用的属性转发Enum基类

如果需要多个类似的Enum类,可以封装一个通用基类实现复用:

import re
import enum
from typing import Any

class ValueForwardingEnum(enum.Enum):
    def __getattr__(self, name: str) -> Any:
        return getattr(self.value, name)

class Patterns(ValueForwardingEnum):
    """
    用于读取xyz文件中类型声明的正则模式
    """
    Simple: re.Pattern = re.compile(r"([\w_]+)\s*[\|;]")
    Complex: re.Pattern = re.compile(r"([\w_]+)\s*:\s*([\w_]+)")

其他需要属性转发功能的Enum类,直接继承这个基类即可。

解决方案3:添加调用方法支持直接执行正则匹配

如果主要使用search、match、findall这类可调用的正则方法,可以给Enum成员添加__call__方法,直接转发到value的调用逻辑:

import re
import enum

class Patterns(enum.Enum):
    """
    用于读取xyz文件中类型声明的正则模式
    """
    Simple: re.Pattern = re.compile(r"([\w_]+)\s*[\|;]")
    Complex: re.Pattern = re.compile(r"([\w_]+)\s*:\s*([\w_]+)")

    def __call__(self, *args, **kwargs):
        return self.value(*args, **kwargs)
    
    def __getattr__(self, name):
        return getattr(self.value, name)

这样既可以直接调用Enum成员执行匹配(比如Patterns.Complex(text)),也能访问其他正则属性和方法。


内容的提问来源于stack exchange,提问作者globglogabgalab

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.12 08:43:11