Python StrEnum的value_of实现能否更优雅地改写?
Python StrEnum的value_of实现能否更优雅地改写?
嘿,这个问题提得很实在!你当前的value_of功能完全没问题,但嵌套的try-except确实显得有点冗余,咱们可以用更符合Python风格的写法来优化,既保持可读性,又让代码更清爽。
我给你两种常见的优化方向,你可以根据自己的需求选:
方案一:利用Enum内部的映射字典(最简洁)
Enum类其实内部维护了两个非常实用的映射:
_member_map_:键是枚举成员的名称(比如'BANANA'),值是对应的枚举对象_value2member_map_:键是枚举成员的取值(比如'Banana'),值是对应的枚举对象
咱们可以直接用这两个字典的get方法来实现,完全不用写try-except:
from enum import Enum class StrEnum(str, Enum): """Enum with str values""" pass class BaseStrEnum(StrEnum): """Base Enum""" @classmethod def value_of(cls, value): # 先按成员名查找,找不到再按值查找,都找不到返回None return cls._member_map_.get(value) or cls._value2member_map_.get(value, None)
测试一下你的示例代码,效果完全一致:
class Fruits(BaseStrEnum): BANANA = "Banana" PEA = "Pea" APPLE = "Apple" print(Fruits.value_of('BANANA')) # 输出: Fruits.BANANA print(Fruits.value_of('Banana')) # 输出: Fruits.BANANA print(Fruits.value_of('invalid')) # 输出: None
注意:这两个映射是以下划线开头的“私有”属性,虽然在Python的各个版本里都很稳定,但官方没有公开承诺永不修改。如果你的代码需要严格遵循“不依赖非公开API”的规范,可以看看下面的方案。
方案二:扁平化try-except结构(更稳妥)
如果不想碰内部属性,咱们可以把嵌套的try-except改成扁平的循环尝试,代码更易读:
from enum import Enum class StrEnum(str, Enum): """Enum with str values""" pass class BaseStrEnum(StrEnum): """Base Enum""" @classmethod def value_of(cls, value): # 把两种查找方式放到一个元组里,依次尝试 for lookup_func in (cls.__getitem__, cls): try: return lookup_func(value) except (KeyError, ValueError): continue # 所有方式都失败,返回None return None
这里的cls.__getitem__就是cls[value]的底层实现,对应按成员名查找;cls本身作为调用的话,就是cls(value),对应按值查找。循环尝试两种方式,只要有一个成功就返回,都失败就返回None,结构比嵌套try-except清爽多了。
两种方案对比
- 方案一的代码最简洁,查找效率也高,但依赖Enum的内部属性
- 方案二更符合“不依赖私有API”的编程习惯,代码也足够清晰
你可以根据自己的项目规范来选择~
备注:内容来源于stack exchange,提问作者SkyWalker
相关产品推荐
相关产品推荐

