如何在Python中将int转换为枚举类型?

169
使用新的枚举特性(通过 backport enum34)与 python 2.7.6。
给定以下定义,如何将 int 转换为相应的枚举值?
from enum import Enum

class Fruit(Enum):
    Apple = 4
    Orange = 5
    Pear = 6

我知道我可以手动编写一系列if语句来进行转换,但是是否有一种简单的Python方式来进行转换?基本上,我想要一个函数ConvertIntToFruit(int),它返回一个枚举值。

我的用例是,我有一个记录的csv文件,我正在将每个记录读入对象中。其中一个文件字段是表示枚举的整数字段。当我填充对象时,我想将文件中的整数字段转换为对象中相应的枚举值。

5个回答

290

你可以“调用”Enum类:

Fruit(5)

5 转换为 Fruit.Orange

>>> from enum import Enum
>>> class Fruit(Enum):
...     Apple = 4
...     Orange = 5
...     Pear = 6
... 
>>> Fruit(5)
<Fruit.Orange: 5>

从文档的编程访问枚举成员及其属性部分:

Sometimes it’s useful to access members in enumerations programmatically (i.e. situations where Color.red won’t do because the exact color is not known at program-writing time). Enum allows such access:

>>> Color(1)
<Color.red: 1>
>>> Color(3)
<Color.blue: 3>
在相关说明中:要映射包含枚举成员名称的字符串值,请使用订阅:
>>> s = 'Apple'
>>> Fruit[s]
<Fruit.Apple: 4>

谢谢,我在重新阅读文档时得到了这个。第一次浏览时对我来说不太清楚。我刚刚尝试使用字符串,并且很高兴看到当枚举值也是字符串时它可以工作,我假设任何任意对象值也是如此。 - User
非常好,所以转换是按值传递的。除了通过列表推导式过滤枚举列表并在名称属性上匹配之外,是否还有类似于按名称传递的模拟方法? - jxramos
5
@jxramos请查看我的回答中的文档链接,里面有明确的说明。使用项目访问:Fruit['Orange'] - Martijn Pieters
太棒了!我在页面上搜索了 convertcoercecast,但没有找到任何结果。看起来魔法是“通过名称访问枚举成员,使用项访问”。非常完美,非常感谢,我将使用这种语法来清理我的代码。 - jxramos
更酷的是,我可以使用像 "foobar" in Fruit.__members__ 这样的东西来测试成员资格,甚至可以使用 Fruit.get('foobar', Fruit.Orange) 来获取默认的枚举口味。我的代码看起来更简化了,删除了我之前放置的所有这些附属查找脚手架。 - jxramos

2
我认为简单来说就是通过调用EnumType(int_value)int值转换为Enum,然后访问Enum对象的name属性。这样可以更加通俗易懂地表达。
my_fruit_from_int = Fruit(5) #convert to int
fruit_name = my_fruit_from_int.name #get the name
print(fruit_name) #Orange will be printed here

作为一个函数:

或者作为一个函数:

def convert_int_to_fruit(int_value):
    try:
        my_fruit_from_int = Fruit(int_value)
        return my_fruit_from_int.name
    except:
        return None

1
class Status(IntEnum):
    UPLOADED = 1
    DOWNLOADED = 5
    SEGMENTED = 10    
    DIRECTED = 15
    READYTODEEP = 20

获得枚举值;
statusId = 5
Status(statusId)

获得枚举值的字符串表示:

statusId = 5
print(Status(statusId).name)

1

我想要类似的东西,以便我可以从单个引用中访问值对的任一部分。 原始版本:

#!/usr/bin/env python3


from enum import IntEnum


class EnumDemo(IntEnum):
    ENUM_ZERO       = 0
    ENUM_ONE        = 1
    ENUM_TWO        = 2
    ENUM_THREE      = 3
    ENUM_INVALID    = 4


#endclass.


print('Passes')
print('1) %d'%(EnumDemo['ENUM_TWO']))
print('2) %s'%(EnumDemo['ENUM_TWO']))
print('3) %s'%(EnumDemo.ENUM_TWO.name))
print('4) %d'%(EnumDemo.ENUM_TWO))
print()


print('Fails')
print('1) %d'%(EnumDemo.ENUM_TWOa))

失败会抛出预期的异常。

更健壮的版本:

#!/usr/bin/env python3


class EnumDemo():


    enumeration =   (
                        'ENUM_ZERO',    # 0.
                        'ENUM_ONE',     # 1.
                        'ENUM_TWO',     # 2.
                        'ENUM_THREE',   # 3.
                        'ENUM_INVALID'  # 4.
                    )


    def name(self, val):
        try:

            name = self.enumeration[val]
        except IndexError:

            # Always return last tuple.
            name = self.enumeration[len(self.enumeration) - 1]

        return name


    def number(self, val):
        try:

            index = self.enumeration.index(val)
        except (TypeError, ValueError):

            # Always return last tuple.
            index = (len(self.enumeration) - 1)

        return index


#endclass.


print('Passes')
print('1) %d'%(EnumDemo().number('ENUM_TWO')))
print('2) %s'%(EnumDemo().number('ENUM_TWO')))
print('3) %s'%(EnumDemo().name(1)))
print('4) %s'%(EnumDemo().enumeration[1]))
print()
print('Fails')
print('1) %d'%(EnumDemo().number('ENUM_THREEa')))
print('2) %s'%(EnumDemo().number('ENUM_THREEa')))
print('3) %s'%(EnumDemo().name(11)))
print('4) %s'%(EnumDemo().enumeration[-1]))

如果没有正确使用,这将避免创建异常,而是返回故障指示。更Pythonic的方法是返回“None”,但我的特定应用程序直接使用文本。


为什么不在枚举实例上定义__int____str__方法呢? - Tim

1
你可以通过以下方式获取枚举常量的名称字符串:

name()

Fruit(5).name

您可以通过以下方式获取枚举类型的整型值

Fruit(5).value

你可以像这样获取枚举对象:

Fruit(5)

测试你的类:

from enum import Enum

class Fruit(Enum):
    Apple = 4
    Orange = 5
    Pear = 6

像这样:

>>> Fruit(5)
<Fruit.Orange: 5>
>>> Fruit(5).name
'Orange'
>>> Fruit(5).value
5

>>> Fruit['Apple']
<Fruit.Apple: 4>
>>> Fruit['Apple'].value
4
>>> Fruit['Apple'].name
'Apple'

当你想要从 int 转换时,你可以像调用一个函数一样访问它。

而当你想要从 string 转换时,你需要使用方括号进行访问。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接