假设我有一个预先存在的映射作为字典:
value_map = {'a': 1, 'b': 2}
我可以这样创建一个枚举类:
from enum import Enum
MyEnum = Enum('MyEnum', value_map)
像这样使用
a = MyEnum.a
print(a.value)
>>> 1
print(a.name)
>>> 'a'
但是然后我想为我的新枚举类定义一些方法:
def double_value(self):
return self.value * 2
当然,我可以这样做:
class MyEnum(Enum):
a = 1
b = 2
@property
def double_value(self):
return self.value * 2
但是正如我所说,我必须使用预定义的值映射字典,所以我不能这样做。如何做到这一点?我试图从另一个类(定义为mixin)继承该方法,但我无法弄清楚。
您可以将带有mixin方法的基本类型与type
参数一起传递给功能性API :
>>> import enum
>>> value_map = {'a': 1, 'b': 2}
>>> class DoubledEnum:
... @property
... def double_value(self):
... return self.value * 2
...
>>> MyEnum = enum.Enum('MyEnum', value_map, type=DoubledEnum)
>>> MyEnum.a.double_value
2
对于一个全功能的做法,从来没有使用class
的语句,你可以创建基MIX-与type()
功能:
DoubledEnum = type('DoubledEnum', (), {'double_value': property(double_value)})
MyEnum = enum.Enum('MyEnum', value_map, type=DoubledEnum)
您还可以使用enum.EnumMeta()
与创建class MyEnum(enum.Enum): ...
子类时Python相同的方式使用元类:
__prepare__
(enum.Enum,)
步骤1中创建的类名称,基数(此处)和类字典。使用的自定义字典子类enum.EnumMeta
并不是为易于重用而设计的。它实现了一个__setitem__
记录元数据的钩子,但没有覆盖该dict.update()
方法,因此在使用value_map
字典时我们需要格外小心:
import enum
def enum_with_extras(name, value_map, bases=enum.Enum, **extras):
if not isinstance(bases, tuple):
bases = bases,
if not any(issubclass(b, enum.Enum) for b in bases):
bases += enum.Enum,
classdict = enum.EnumMeta.__prepare__(name, bases)
for key, value in {**value_map, **extras}.items():
classdict[key] = value
return enum.EnumMeta(name, bases, classdict)
然后传入double_value=property(double_value)
该函数(连同枚举名称和value_map
字典):
>>> def double_value(self):
... return self.value * 2
...
>>> MyEnum = enum_with_extras('MyEnum', value_map, double_value=property(double_value))
>>> MyEnum.a
<MyEnum.a: 1>
>>> MyEnum.a.double_value
2
否则,您可以创建不带成员的枚举的子类(任何不是描述符的成员,因此函数,属性,类方法等),因此可以先定义不带成员的枚举:
class DoubledEnum(enum.Enum):
@property
def double_value(self):
return self.value * 2
对于功能性API(例如enum.Enum(..., type=DoubledEnum)
)和我编码为的元类方法,这都是可接受的基类enum_with_extras()
。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句