示例:
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
参考:https://docs.python.org/3/library/enum.html#planet
为什么我要这样做?如果构造函数列表中有一些原始类型(int,bool),那么使用命名参数会很好。
答案 0 :(得分:25)
虽然您不能按照使用枚举描述的方式使用命名参数,但您可以使用namedtuple
mixin获得类似的效果:
from collections import namedtuple
from enum import Enum
Body = namedtuple("Body", ["mass", "radius"])
class Planet(Body, Enum):
MERCURY = Body(mass=3.303e+23, radius=2.4397e6)
VENUS = Body(mass=4.869e+24, radius=6.0518e6)
EARTH = Body(mass=5.976e+24, radius=3.3972e6)
# ... etc.
...我认为更清洁,因为您不必编写__init__
方法。
使用示例:
>>> Planet.MERCURY
<Planet.MERCURY: Body(mass=3.303e+23, radius=2439700.0)>
>>> Planet.EARTH.mass
5.976e+24
>>> Planet.VENUS.radius
6051800.0
请注意,根据the docs,“混合类型必须出现在基础序列中Enum
之前”。
答案 1 :(得分:10)
@ zero-piraeus接受的答案可以略微扩展,以允许默认参数。当你有一个大的枚举,大多数条目具有相同的元素值时,这非常方便。
class Body(namedtuple('Body', "mass radius moons")):
def __new__(cls, mass, radius, moons=0):
return super().__new__(cls, mass, radius, moons)
def __getnewargs__(self):
return (self.mass, self.radius, self.moons)
class Planet(Body, Enum):
MERCURY = Body(mass=3.303e+23, radius=2.4397e6)
VENUS = Body(mass=4.869e+24, radius=6.0518e6)
EARTH = Body(5.976e+24, 3.3972e6, moons=1)
如果没有__getnewargs__
,请注意酸洗不起作用。
class Foo:
def __init__(self):
self.planet = Planet.EARTH # pickle error in deepcopy
from copy import deepcopy
f1 = Foo()
f2 = deepcopy(f1) # pickle error here
答案 2 :(得分:3)
如果超出namedtuple
混合,请查看aenum
库 1 。除了为Enum
添加一些额外的铃声和口哨声之外,它还支持NamedConstant
和基于元类的NamedTuple
。
使用aenum.Enum
上面的代码可能如下所示:
from aenum import Enum, enum, _reduce_ex_by_name
class Planet(Enum, init='mass radius'):
MERCURY = enum(mass=3.303e+23, radius=2.4397e6)
VENUS = enum(mass=4.869e+24, radius=6.0518e6)
EARTH = enum(mass=5.976e+24, radius=3.3972e6)
# replace __reduce_ex__ so pickling works
__reduce_ex__ = _reduce_ex_by_name
并在使用中:
--> for p in Planet:
... print(repr(p))
<Planet.MERCURY: enum(radius=2439700.0, mass=3.3030000000000001e+23)>
<Planet.EARTH: enum(radius=3397200.0, mass=5.9760000000000004e+24)>
<Planet.VENUS: enum(radius=6051800.0, mass=4.8690000000000001e+24)>
--> print(Planet.VENUS.mass)
4.869e+24
1 披露:我是Python stdlib Enum
,enum34
backport和Advanced Enumeration (aenum
)图书馆的作者。
答案 3 :(得分:0)
对于Python 3.6.1+,可以使用typing.NamedTuple,它还允许设置默认值,从而产生更漂亮的代码。 @ shao.lo的示例如下所示:
from enum import Enum
from typing import NamedTuple
class Body(NamedTuple):
mass: float
radius: float
moons: int=0
class Planet(Body, Enum):
MERCURY = Body(mass=3.303e+23, radius=2.4397e6)
VENUS = Body(mass=4.869e+24, radius=6.0518e6)
EARTH = Body(5.976e+24, 3.3972e6, moons=1)
这也支持酸洗。如果您不想指定类型,则可以使用任何类型。
感谢@ monk-time,他的回答here启发了该解决方案。