代码之家  ›  专栏  ›  技术社区  ›  Bernard

有没有更好的方法在Python中获取命名的常量系列(枚举)?[副本]

  •  17
  • Bernard  · 技术社区  · 16 年前

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

    那么你当然可以这样说:

    constant_list.A_CONSTANT
    

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

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

    constant_dic["A_CONSTANT"]
    

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

    提前谢谢。

    6 回复  |  直到 16 年前
        1
  •  19
  •   Bernard    16 年前

    对于2.3或之后:

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

    使用:

     codes = Enumerate('FOO BAR BAZ')
    

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

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

    这是从 here )

        2
  •  2
  •   Simon Peverett    16 年前

    我找到枚举类配方(活动状态, Python Cookbook

    另外,它有一个查找功能,这是很好的。

        3
  •  2
  •   Anthony Cramp    16 年前

    恒定dic的另一种结构:

    constants = ["A_CONSTANT", "B_CONSTANT", "C_CONSTANT"]
    constant_dic = dict([(c,i) for i, c in enumerate(constants)])
    
        4
  •  2
  •   Kevin Little    16 年前

    下面的行为类似于classisc“Write in stone”C枚举——一旦定义,就不能更改它,只能读取它的值。你也不能实例化它。您所要做的就是“导入enum.py”并从类enum派生。

    # 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!")
    

    # 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...)"
    
        5
  •  2
  •   steveha    15 年前

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

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

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

        6
  •  1
  •   Dzinx    16 年前

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

    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)
    

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