具有重复值的Python枚举

zep*_*hyr 5 python enums

我在使用一些属性具有相同值的枚举时遇到麻烦。我认为Enums对python来说是如此新奇,以至于我找不到关于此问题的任何其他参考。无论如何,假设我有以下情况

class CardNumber(Enum):
    ACE      = 11
    TWO      = 2
    THREE    = 3
    FOUR     = 4
    FIVE     = 5
    SIX      = 6
    SEVEN    = 7
    EIGHT    = 8
    NINE     = 9
    TEN      = 10
    JACK     = 10
    QUEEN    = 10
    KING     = 10
Run Code Online (Sandbox Code Playgroud)

显然,这些是黑色插孔中的卡号及其对应的值。十个通王具有相同的价值。但是如果我做这样的事情print(CardNumber.QUEEN),我会回来的<CardNumber.TEN: 10>。更重要的是,如果我遍历这些,它只会遍历唯一值。

>>> for elem in CardNumber:
...     print(elem)
CardNumber.ACE
CardNumber.TWO
CardNumber.THREE
CardNumber.FOUR
CardNumber.FIVE
CardNumber.SIX
CardNumber.SEVEN
CardNumber.EIGHT
CardNumber.NINE
CardNumber.TEN
Run Code Online (Sandbox Code Playgroud)

我该如何解决这个问题?我希望CardNumber.QUEEN和CardNumber.TEN是唯一的,并且都出现在任何迭代中。我唯一能想到的就是为每个属性赋予第二个值,该值将充当一个不同的id,但这似乎是不可思议的。

Mar*_*ers 7

是的,具有重复值的标签会变成第一个此类标签的别名。

您可以枚举__members__属性,它是一个包含别名的有序字典:

>>> for name, value in CardNumber.__members__.items():
...     print(name, value)
... 
ACE CardNumber.ACE
TWO CardNumber.TWO
THREE CardNumber.THREE
FOUR CardNumber.FOUR
FIVE CardNumber.FIVE
SIX CardNumber.SIX
SEVEN CardNumber.SEVEN
EIGHT CardNumber.EIGHT
NINE CardNumber.NINE
TEN CardNumber.TEN
JACK CardNumber.TEN
QUEEN CardNumber.TEN
KING CardNumber.TEN
Run Code Online (Sandbox Code Playgroud)

但是,如果您必须拥有唯一(而不是别名)的标签和值对,那么enum.Enum这里的方法是错误的;它与纸牌游戏的用例不匹配。

在这种情况下,最好使用字典(collections.OrderedDict()如果顺序也很重要,请考虑使用)。


Eth*_*man 6

更新资料

使用1,您有两种选择:aenum

  • NamedConstant改为使用:不提供任何Enum额外功能(迭代,查找等)。[请参阅:下面的原始答案]

  • use NoAlias:具有所有普通Enum行为,但每个成员都是唯一的,并且按值查找不可用

一个例子NoAlias

from aenum import Enum, NoAlias

class CardNumber(Enum):

    _order_ = 'EIGHT NINE TEN JACK QUEEN KING ACE'  # only needed for Python 2.x
    _settings_ = NoAlias

    EIGHT    = 8
    NINE     = 9
    TEN      = 10
    JACK     = 10
    QUEEN    = 10
    KING     = 10
    ACE      = 11
Run Code Online (Sandbox Code Playgroud)

并在使用中:

>>> list(CardNumber)
[<CardNumber.EIGHT: 8>, <CardNumber.NINE: 9>, <CardNumber.TEN: 10>, <CardNumber.JACK: 10>, <CardNumber.QUEEN: 10>, <CardNumber.KING: 10>, <CardNumber.ACE: 11>]

>>> CardNumber.QUEEN == CardNumber.KING
False

>>> CardNumber.QUEEN is CardNumber.KING
False

>>> CardNumber.QUEEN.value == CardNumber.KING.value
True

>>> CardNumber(8)
Traceback (most recent call last):
  ...
TypeError: NoAlias enumerations cannot be looked up by value
Run Code Online (Sandbox Code Playgroud)

原始答案

如果您想使用命名常量而不关心Enums 的其他功能,则可以使用aenum库中NamedConstant类:

from aenum import NamedConstant

class CardNumber(NamedConstant):
    ACE      = 11
    TWO      = 2
    THREE    = 3
    FOUR     = 4
    FIVE     = 5
    SIX      = 6
    SEVEN    = 7
    EIGHT    = 8
    NINE     = 9
    TEN      = 10
    JACK     = 10
    QUEEN    = 10
    KING     = 10
Run Code Online (Sandbox Code Playgroud)

重复值仍然不同:

>>> CardNumber.TEN is CardNumber.JACK
False

>>> CardNumber.TEN == CardNumber.JACK
True

>>> CardNumber.TEN == 10
True
Run Code Online (Sandbox Code Playgroud)

1披露:我是Python stdlibEnumenum34backportAdvanced Enumeration(aenum 库的作者。