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

Posted

技术标签:

【中文标题】我应该如何最好地模拟和/或避免 Python 中的枚举? [复制]【英文标题】:How should I best emulate and/or avoid enum's in Python? [duplicate] 【发布时间】:2010-09-11 15:11:15 【问题描述】:

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

类代码在这里:

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)

【问题讨论】:

同意。抱歉,我应该早点找到的。 【参考方案1】:

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

枚举:http://pypi.python.org/pypi/enum SymbolType(与枚举不太一样,但仍然有用):http://pypi.python.org/pypi/SymbolType Or just do a search

【讨论】:

【参考方案2】:

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

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 )

【讨论】:

【参考方案3】:

here 有很多很好的讨论。

【讨论】:

【参考方案4】:

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

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_BAZ2 更清晰。

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

【讨论】:

【参考方案5】:

枚举的内置方法是:

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

这适用于小型集合,但有一些缺点:

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

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

【讨论】:

值得注意的是,如果范围大小与元素计数不匹配,Python 将引发异常。【参考方案6】:

我从看起来很像 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

【讨论】:

以上是关于我应该如何最好地模拟和/或避免 Python 中的枚举? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

同时安装多个 Python 发行版会遇到啥问题,以及如何最好地避免这些问题? [复制]

如何使用 Node.js 为所有连接最好地实现 HTTPS?

如何在 Python 中最好地保存多个类实例?更新:如何腌制包含 osgeo.ogr 对象的类实例?

如何最好地处理 Neuraxle 管道中的错误和/或丢失数据?

使用 ASP.NET MVC,如何最好地避免同时编写添加视图和编辑视图?

如何在 Flutter 集成测试中最好地存根/模拟 rest API 调用