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

在Python中,我应该如何最好地模拟和/或避免枚举?[复制品]

  •  5
  • Lanny  · 技术社区  · 17 年前

    这个问题已经有了答案:

    我在一些Python项目中使用了一个小类来模拟枚举。有没有更好的方法,或者在某些情况下这是最有意义的?

    此处为类代码:

    class Enum(object):
    '''Simple Enum Class
    Example Usage:
    >>> codes = Enum('FOO BAR BAZ') # codes.BAZ will be 2 and so on ...'''
    def __init__(self, names):
        for number, name in enumerate(names.split()):
            setattr(self, name, number)
    
    6 回复  |  直到 15 年前
        1
  •  3
  •   Community Mohan Dere    8 年前

    有很多好的讨论 here .

        2
  •  5
  •   Ycros    17 年前

    以前已建议将枚举包含到语言中,但被拒绝(请参见 http://www.python.org/dev/peps/pep-0354/ ,尽管您可以使用现有的包,而不是编写自己的实现:

        3
  •  4
  •   S.Lott    17 年前

    最常见的枚举情况是作为状态或策略设计模式一部分的枚举值。枚举是要使用的特定状态或特定可选策略。在这种情况下,它们几乎总是某些类定义的一部分。

    class DoTheNeedful( object ):
        ONE_CHOICE = 1
        ANOTHER_CHOICE = 2 
        YET_ANOTHER = 99
        def __init__( self, aSelection ):
            assert aSelection in ( self.ONE_CHOICE, self.ANOTHER_CHOICE, self.YET_ANOTHER )
            self.selection= aSelection
    

    然后,在这个类的客户机中。

    dtn = DoTheNeeful( DoTheNeeful.ONE_CHOICE )
    
        4
  •  3
  •   Charles Duffy    17 年前

    我更经常看到的是,在顶层模块上下文中:

    FOO_BAR = 'FOO_BAR'
    FOO_BAZ = 'FOO_BAZ'
    FOO_QUX = 'FOO_QUX'
    

    ……后来…

    if something is FOO_BAR: pass # do something here
    elif something is FOO_BAZ: pass # do something else
    elif something is FOO_QUX: pass # do something else
    else: raise Exception('Invalid value for something')
    

    注意使用 is 而不是 == 在这里冒险——假设人们正在使用 your_module.FOO_BAR 而不是字符串 'FOO_BAR' (将 正常地 被拘留到这样的程度 将匹配,但这肯定不能指望),因此根据上下文可能不合适。

    这样做的一个好处是,通过查看存储该字符串的引用的任何位置,可以立即发现它的来源; FOO_BAZ 不那么模棱两可 2 .

    除此之外,还有一件事冒犯了我对蟒蛇的敏感,那就是你所建议的职业是使用 split() . 为什么不先传入一个元组、列表或其他可枚举项?

        5
  •  2
  •   tsg    17 年前

    执行枚举的内置方法是:

    (FOO, BAR, BAZ) = range(3)
    

    它对小装置很有用,但也有一些缺点:

    • 你需要手工计算元素的数量
    • 不能跳过值
    • 如果添加一个名称,还需要更新范围号

    有关python中的完整枚举实现,请参见: http://code.activestate.com/recipes/67107/

        6
  •  1
  •   Spell    17 年前

    我从看起来很像s.lott的答案开始,但我只重载了“str”和“eq”(而不是整个对象类),这样我就可以打印和比较枚举的值。

    class enumSeason():
        Spring = 0
        Summer = 1
        Fall = 2
        Winter = 3
        def __init__(self, Type):
            self.value = Type
        def __str__(self):
            if self.value == enumSeason.Spring:
                return 'Spring'
            if self.value == enumSeason.Summer:
                return 'Summer'
            if self.value == enumSeason.Fall:
                return 'Fall'
            if self.value == enumSeason.Winter:
                return 'Winter'
        def __eq__(self,y):
            return self.value==y.value
    

    print(x)将生成名称而不是值,两个保持弹簧的值将相等。

       >>> x = enumSeason(enumSeason.Spring)
       >>> print(x)
       Spring
       >>> y = enumSeason(enumSeason.Spring)
       >>> x == y
       True