使用枚举时,我更喜欢不必在任何地方使用.value
来访问成员属性。
所以,我这样创建它们:
from dataclasses import dataclass
from enum import Enum
@dataclass
class Item:
foo: int
bar: int
class Collection(Item, Enum):
A = 1, 2
# Now I can use Collection.A.foo
但是,我的Item
类有几个参数,为了可读性(和IDE支持(,我更喜欢直接在Enum上实例化Items。类似这样的东西(这不起作用,因为Enum想要一个位置参数的元组,而不是Item
的实例(:
class Collection(Item, Enum):
A = Item(1, 2)
同时仍然享受Collection.A.foo
属性访问(而不是Collection.A.value.foo
,如果我有Collection(Enum)
,我会得到它(。
或者至少能够指定用于实例化Item
:的关键字
class Collection(Item, Enum):
A = dict(1, 2)
有没有办法实现这两种解决方案?也许是Item.__new__
的黑客攻击?
编辑:我尽量不在枚举中使用元组。(在撰写本文时,两个答案仍然使用元组来定义Items的参数。(
从Python的Enum
文档中-您可以尝试重写枚举类的__init__
或__new__
,并获得所需的输出。
请注意文件中关于何时覆盖哪一个的以下部分:
何时使用__new__((与__init__((
每当您想要自定义枚举成员的实际值时,都必须使用new((。任何其他修改都可以在__new__((或__init__((中进行,首选__init__(。
例如,如果您想将几个项传递给构造函数,但只希望其中一个为值(请参阅
__new__
重写(
看看这两个例子:
覆盖__new__
:
>>> class Coordinate(bytes, Enum):
... """
... Coordinate with binary codes that can be indexed by the int code.
... """
... def __new__(cls, value, label, unit):
... obj = bytes.__new__(cls, [value])
... obj._value_ = value
... obj.label = label
... obj.unit = unit
... return obj
... PX = (0, 'P.X', 'km')
... PY = (1, 'P.Y', 'km')
... VX = (2, 'V.X', 'km/s')
... VY = (3, 'V.Y', 'km/s')
...
>>> print(Coordinate['PY'])
Coordinate.PY
>>> print(Coordinate(3))
Coordinate.VY
覆盖__init__
:
>>> class Planet(Enum):
... MERCURY = (3.303e+23, 2.4397e6)
... VENUS = (4.869e+24, 6.0518e6)
... EARTH = (5.976e+24, 6.37814e6)
... MARS = (6.421e+23, 3.3972e6)
... JUPITER = (1.9e+27, 7.1492e7)
... SATURN = (5.688e+26, 6.0268e7)
... URANUS = (8.686e+25, 2.5559e7)
... NEPTUNE = (1.024e+26, 2.4746e7)
... def __init__(self, mass, radius):
... self.mass = mass # in kilograms
... self.radius = radius # in meters
... @property
... def surface_gravity(self):
... # universal gravitational constant (m3 kg-1 s-2)
... G = 6.67300E-11
... return G * self.mass / (self.radius * self.radius)
...
>>> Planet.EARTH.value
(5.976e+24, 6378140.0)
>>> Planet.EARTH.surface_gravity
9.802652743337129
通过使用其中一种方法,您可以创建自己的、更可定制的Enum类。即使您还需要Item
类作为一个独立于枚举的类,您也可以覆盖这两个函数中的一个并使其工作(尽管如果Item
只是为了枚举而创建的,您可能应该在内部合并它(。
我认为您可以尝试__init__
方法中的传统设置方式,该方法不需要额外的类。详细的解释可以在这里找到。
from enum import Enum
class Collection(Enum):
A = 1, 2
B = 3, 4
C = 5, 6
D = 7, 8
def __init__(self, foo, bar):
self.foo = foo
self.bar = bar
试运行
for item in Collection:
print(item.foo, item.bar, sep=', ')
结果
1, 2 3, 4 5, 6 7, 8