我想通过读取YAML文件中的值在运行时创建枚举类型.所以我有这个:
# Fetch the values
v = {'foo':42, 'bar':24}
# Create the enum
e = type('Enum', (), v)
Run Code Online (Sandbox Code Playgroud)
有没有正确的方法呢?我觉得打电话type不是一个非常简洁的解决方案.
例:
class Planet(Enum):
MERCURY = (mass: 3.303e+23, radius: 2.4397e6)
def __init__(self, mass, radius):
self.mass = mass # in kilograms
self.radius = radius # in meters
Run Code Online (Sandbox Code Playgroud)
参考:https://docs.python.org/3/library/enum.html#planet
我为什么要这样做?如果构造函数列表中有一些原始类型(int,bool),那么使用命名参数会很好.
注意 这个问题与Python 3 Enum数据类型无关,它只是我正在使用的示例.
使用PEP 3115, Python 3添加了1方法,以便在创建类时允许使用自定义命名空间.例如,新数据类型用于返回私有实例以用作新类的命名空间.__prepare__typeEnum__prepare___EnumDictEnum
但是,我在SO 2中看到了几个关于EnumMeta子类的例子,在元类__new__方法中为类创建了一个新的命名空间,而不是调用__prepare__方法来获取新的命名空间type(clsdict)().这样做有风险吗?
1 签名__prepare__:
@classmethod
def __prepare__(metacls, cls, bases, **kwds):
Run Code Online (Sandbox Code Playgroud)
并为__new__:
def __new__(metacls, cls, bases, clsdict, **kwds):
Run Code Online (Sandbox Code Playgroud)
2 示例使用type(clsdict):
从这个答案
class CountryCodeMeta(enum.EnumMeta):
def __new__(metacls, cls, bases, classdict):
data = classdict['data']
names = [(country['alpha-2'], int(country['country-code'])) for country in data]
--> temp = type(classdict)()
for name, value in …Run Code Online (Sandbox Code Playgroud) 在本文中, Nick Coghlan讨论了PEP 435 Enum类型的一些设计决策,以及如何EnumMeta进行子类化以提供不同的Enum体验。
但是,我给出的建议(我是stdlib的主要Enum作者)关于使用元类的建议是,在没有充分好的理由的情况下不应该这样做-例如,无法使用类装饰器或专用工具来完成所需的工作隐藏任何丑陋的功能;而在我自己的工作,我已经能够做到我需要什么简单的使用__new__,__init__在创建时,和/或正常类/实例方法Enum类:
然后是一个警告性的故事,在研究Enum,有和没有元类子类化时要小心:
考虑到所有这些,我什么时候需要摆弄EnumMeta自己?