วิธีการแปลง int เป็น Enum ใน python?


96

ใช้คุณลักษณะ Enum ใหม่ (ผ่านbackport enum34 ) กับ python 2.7.6

ด้วยคำจำกัดความต่อไปนี้ฉันจะแปลง int เป็นค่า Enum ที่สอดคล้องกันได้อย่างไร

from enum import Enum

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

ฉันรู้ว่าฉันสามารถสร้างชุดคำสั่ง if เพื่อทำการแปลงได้ แต่มีวิธีง่ายๆในการแปลงหรือไม่ โดยทั่วไปฉันต้องการฟังก์ชั่น ConvertIntToFruit (int) ที่ส่งคืนค่า enum

กรณีการใช้งานของฉันคือฉันมีไฟล์ csv ของเร็กคอร์ดที่ฉันกำลังอ่านแต่ละเร็กคอร์ดในอ็อบเจ็กต์ หนึ่งในฟิลด์ไฟล์คือฟิลด์จำนวนเต็มที่แสดงถึงการแจงนับ ขณะที่ฉันกำลังเติมวัตถุฉันต้องการแปลงฟิลด์จำนวนเต็มจากไฟล์เป็นค่า Enum ที่สอดคล้องกันในออบเจ็กต์

คำตอบ:


165

คุณ 'เรียก' Enumชั้นเรียน:

Fruit(5)

เพื่อเปลี่ยน5เป็นFruit.Orange:

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

จากการเข้าถึงแบบเป็นโปรแกรมไปยังสมาชิกการแจงนับและส่วนแอตทริบิวต์ของเอกสารประกอบ:

บางครั้งก็มีประโยชน์ในการเข้าถึงสมาชิกในการแจงนับทางโปรแกรม (เช่นสถานการณ์ที่Color.redไม่สามารถทำได้เนื่องจากไม่ทราบสีที่แน่นอนในเวลาเขียนโปรแกรม) Enumอนุญาตให้เข้าถึงดังกล่าว:

>>> Color(1)
<Color.red: 1>
>>> Color(3)
<Color.blue: 3>

ในหมายเหตุที่เกี่ยวข้อง: ในการแมปค่าสตริงที่มีชื่อของสมาชิก enum ให้ใช้การสมัครสมาชิก:

>>> s = 'Apple'
>>> Fruit[s]
<Fruit.Apple: 4>

ขอบคุณที่ได้รับสิ่งนี้ในขณะที่ฉันกำลังอ่านเอกสารอีกครั้ง ไม่ชัดเจนสำหรับฉันเกี่ยวกับการอ่านครั้งแรกของฉัน นอกจากนี้ฉันเพิ่งลองใช้สตริงและยินดีที่ได้เห็นว่ามันใช้งานได้เมื่อค่าการแจงนับเป็นสตริงเช่นกันและฉันสมมติว่าค่าวัตถุใด ๆ โดยพลการ
ผู้ใช้

ดีมากดังนั้นการแปลงจึงเป็นไปตามมูลค่า มีอะนาล็อกสำหรับชื่ออื่นนอกเหนือจากความเข้าใจในรายการเพื่อกรองรายการ enum และจับคู่กับแอตทริบิวต์ชื่อหรือไม่
jxramos

4
@jxramos ทำตามลิงค์เอกสารในคำตอบของฉันมันครอบคลุมอย่างชัดเจนที่นั่น ใช้การเข้าถึงรายการ: Fruit['Orange'].
Martijn Pieters

บิงโกสุดยอดมาก! ฉันค้นหาหน้าสำหรับconvert, coerceและcastแต่ไม่ได้ตีอะไร access enum members by name, use item accessหน้าตาเหมือนมายากลเป็น Perfecto ขอบคุณมากที่จะล้างรหัสของฉันด้วยไวยากรณ์นี้
jxramos

ที่เจ๋งกว่านั้นคือฉันสามารถใช้สิ่งต่างๆเช่น"foobar" in Fruit.__members__ทดสอบการเป็นสมาชิกและแม้แต่ดึงออกFruit.get( 'foobar', Fruit.Orange )เพื่อให้ได้รสชาติ Enum เริ่มต้นนั้น รหัสของฉันดูง่ายขึ้นมากในการลบโครงนั่งร้านค้นหาอุปกรณ์เสริมทั้งหมดที่ฉันวางไว้ก่อนหน้านี้
jxramos

1

ฉันคิดว่ามันเป็นในคำง่ายๆคือการแปลงintค่าลงEnumโดยการเรียกEnumType(int_value)หลังจากการเข้าถึงว่าnameของEnumวัตถุ:

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

ฉันต้องการสิ่งที่คล้ายกันเพื่อที่ฉันจะสามารถเข้าถึงส่วนใดส่วนหนึ่งของคู่ค่าจากการอ้างอิงเดียว เวอร์ชั่นวานิลลา:

#!/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 ในการทำเช่นนี้คือการส่งกลับ "ไม่มี" แต่แอปพลิเคชันเฉพาะของฉันใช้ข้อความโดยตรง


ทำไมไม่เพียงกำหนด__int__และ__str__วิธีการในอินสแตนซ์ Enum
ทิม
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.