5

我一直在使用一个小类来模拟一些 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)
4

6 回答 6

5

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

于 2008-09-20T15:51:51.080 回答
4

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

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 )
于 2008-09-20T17:32:17.313 回答
3

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

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'通常会被实习以is匹配,但肯定不能指望),所以可能不会根据上下文适当。

这样做的一个好处是,通过查看存储对该字符串的引用的任何地方,它的来源立即显而易见。FOO_BAZ远比2.

除此之外,您建议的课程冒犯了我的 Pythonic 敏感性的另一件事是使用split(). 为什么不直接传入一个元组、列表或其他可枚举的对象呢?

于 2008-09-20T15:58:02.890 回答
3

这里有很多很好的讨论。

于 2008-09-20T15:58:10.067 回答
2

进行枚举的内置方法是:

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

这适用于小型套装,但有一些缺点:

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

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

于 2008-09-20T15:52:20.063 回答
1

我从看起来很像 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) 将产生名称而不是值,并且持有 Spring 的两个值将彼此相等。

   >>> x = enumSeason(enumSeason.Spring)
   >>> print(x)
   Spring
   >>> y = enumSeason(enumSeason.Spring)
   >>> x == y
   True
于 2009-03-23T18:28:48.477 回答