2015-07-21 114 views
1

我在使用某些属性具有相同值的枚举时遇到问题。我认为Enums对python来说是如此的新鲜,以至于我找不到任何其他的参考资料。在任何情况下,假设我有以下几种:带有重复值的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 

显然这些是卡号和它们在黑色插孔中的相应值。十通王有相同的价值。但如果我做了类似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 

我该如何解决这个问题?我想CardNumber.QUEEN和CardNumber.TEN是唯一的,并且都出现在任何迭代中。我能想到的唯一的事情就是给每个属性一个第二个值,这个值可以作为一个独特的ID,但看起来没有问题。

+3

'Enum'显然不是这个的正确选择。为什么不一个OrderedDict'而不是? – jonrsharpe

回答

2

是的,带有重复值的标签将变成第一个这样的标签的别名。

您可以枚举在__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 

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

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

+0

你和jonrsharpe都是正确的,我应该在这种情况下使用Dicts。我只是以此为例,但无论如何,你们帮助我解决了我的问题。 – zephyr

3

更新

使用(aenum)(https://pypi.python.org/pypi/aenum)你有一对夫妇选择:

  • 使用NamedConstant,而不是:不提供任何Enum额外的(迭代,查找等。)[参见:下面原始答案]

  • 使用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 

,并在使用中:

>>> 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 

原来的答案

如果你想命名的常量和不关心的Enum S中的其他功能,则可以使用NamedConstant类从aenum library

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 

重复值仍然不同:

>>> CardNumber.TEN is CardNumber.JACK 
False 

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

>>> CardNumber.TEN == 10 
True 

披露:我是Python stdlib Enumenum34 backportAdvanced Enumeration (aenum)库的作者。