有没有更好的方法在Python中获得一系列命名常量(枚举)?

Is there a better way to get a named series of constants (enumeration) in Python?

本问题已经有最佳答案,请猛点这里访问。

只是看看在Python中获取命名常量的方法。

1
2
class constant_list:
    (A_CONSTANT, B_CONSTANT, C_CONSTANT) = range(3)

当然,你可以这样称呼它:

1
constant_list.A_CONSTANT

我想你可以用字典,用字符串:

1
2
3
4
constant_dic = {
   "A_CONSTANT" : 1,
   "B_CONSTANT" : 2,
   "C_CONSTANT" : 3,}

像这样引用它:

1
constant_dic["A_CONSTANT"]

那么,我的问题很简单。有更好的方法吗?不是说这些不充分,或者说什么,只是好奇——还有我遗漏的其他常见的习语吗?

事先谢谢。


对于2.3或之后:

1
2
3
4
class Enumerate(object):
  def __init__(self, names):
    for number, name in enumerate(names.split()):
      setattr(self, name, number)

使用:

1
 codes = Enumerate('FOO BAR BAZ')

codes.BAZ将是2,依此类推。

如果您只有2.2,请在此之前加上:

1
2
3
4
5
6
7
 from __future__ import generators

 def enumerate(iterable):
   number = 0
   for name in iterable:
     yield number, name
     number += 1

(这是从这里拿的)


这是我见过的最好的一个:"Python中的第一类枚举"

http://code.activestate.com/recipes/413486/

它为您提供一个类,并且该类包含所有枚举。枚举可以相互比较,但没有任何特定的值;不能将它们用作整数值。(一开始我抵制这个,因为我习惯于C枚举,这是整数值。但是,如果不能将它用作整数,就不能错误地将它用作整数,所以总的来说,我认为这是一个胜利。)每个枚举都是一个唯一的对象。可以打印枚举,可以对其进行迭代,可以测试枚举值是否在枚举中。它很完整,很光滑。


下面的行为类似于Classisc"用石头编写"C枚举——一旦定义好,就不能更改它,只能读取它的值。你也不能实例化它。您所要做的就是"import enum.py"并从类枚举派生。

1
2
3
4
5
6
7
8
9
10
11
12
13
# this is enum.py
class EnumException( Exception ):
   pass

class Enum( object ):
   class __metaclass__( type ):
      def __setattr__( cls, name, value ):
         raise EnumException("Can't set Enum class attribute!")
      def __delattr__( cls, name ):
         raise EnumException("Can't delete Enum class attribute!")

   def __init__( self ):
      raise EnumException("Enum cannot be instantiated!")

这是测试代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# this is testenum.py
from enum import *

class ExampleEnum( Enum ):
   A=1
   B=22
   C=333

if __name__ == '__main__' :

   print"ExampleEnum.A |%s|" % ExampleEnum.A
   print"ExampleEnum.B |%s|" % ExampleEnum.B
   print"ExampleEnum.C |%s|" % ExampleEnum.C
   z = ExampleEnum.A
   if z == ExampleEnum.A:
      print"z is A"

   try:
       ExampleEnum.A = 4  
       print"ExampleEnum.A |%s| FAIL!" % ExampleEnum.A
   except EnumException:
       print"Can't change Enum.A (pass...)"

   try:
       del ExampleEnum.A
   except EnumException:
       print"Can't delete Enum.A (pass...)"

   try:
       bad = ExampleEnum()
   except EnumException:
       print"Can't instantiate Enum (pass...)"

常数dic的另一种构造:

1
2
constants = ["A_CONSTANT","B_CONSTANT","C_CONSTANT"]
constant_dic = dict([(c,i) for i, c in enumerate(constants)])

我发现枚举类配方(活动状态、python食谱)非常有效。

另外,它还有一个查找功能,很好。

聚戊酸乙烯酯


在python中,字符串是不可变的,因此它们对于常量比数字更好。在我看来,最好的方法是制作一个将常量保持为字符串的对象:

1
2
3
4
5
6
7
8
9
10
11
class Enumeration(object):
    def __init__(self, possibilities):
        self.possibilities = set(possibilities.split())

    def all(self):
        return sorted(self.possibilities)

    def __getattr__(self, name):
        if name in self.possibilities:
            return name
        raise AttributeError("Invalid constant: %s" % name)

然后您可以这样使用它:

1
2
3
4
5
6
7
8
9
10
11
12
>>> enum = Enumeration("FOO BAR")
>>> print enum.all()
['BAR', 'FOO']
>>> print enum.FOO
FOO
>>> print enum.FOOBAR
Traceback (most recent call last):
  File"enum.py", line 17, in <module>
    print enum.FOOBAR
  File"enum.py", line 11, in __getattr__
    raise AttributeError("Invalid constant: %s" % name)
AttributeError: Invalid constant: FOOBAR