Làm thế nào để chuyển đổi int sang Enum trong python?


96

Sử dụng tính năng Enum mới (thông qua backport enum34 ) với python 2.7.6.

Với định nghĩa sau, làm cách nào tôi có thể chuyển đổi một int thành giá trị Enum tương ứng?

from enum import Enum

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

Tôi biết tôi có thể tạo thủ công một loạt câu lệnh if để thực hiện chuyển đổi nhưng có cách nào dễ dàng để chuyển đổi không? Về cơ bản, tôi muốn một hàm ConvertIntToFruit (int) trả về giá trị enum.

Trường hợp sử dụng của tôi là tôi có một tệp bản ghi csv nơi tôi đang đọc từng bản ghi thành một đối tượng. Một trong các trường tệp là trường số nguyên đại diện cho một kiểu liệt kê. Khi tôi đang điền đối tượng, tôi muốn chuyển đổi trường số nguyên đó từ tệp thành giá trị Enum tương ứng trong đối tượng.

Câu trả lời:


165

Bạn 'gọi' Enumlớp:

Fruit(5)

biến 5thành Fruit.Orange:

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

Từ quyền truy cập có lập trình đến các thành viên điều tra và phần thuộc tính của họ trong tài liệu:

Đôi khi, việc truy cập các thành viên trong bảng liệt kê theo chương trình Color.redsẽ rất hữu ích (tức là các tình huống sẽ không thực hiện được vì không xác định được màu chính xác tại thời điểm viết chương trình). Enumcho phép truy cập như vậy:

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

Trong một lưu ý liên quan: để ánh xạ một giá trị chuỗi có chứa tên của một thành viên enum, hãy sử dụng đăng ký:

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

Cảm ơn vì tôi vừa đọc lại tài liệu này. Tôi không rõ ràng trong lần đọc lướt đầu tiên. Ngoài ra, tôi vừa thử sử dụng một chuỗi và rất vui khi thấy rằng nó hoạt động khi giá trị liệt kê cũng là một chuỗi và tôi đang giả định bất kỳ giá trị đối tượng tùy ý nào.
Người dùng

Rất tốt, vì vậy chuyển đổi là theo giá trị. Có một phương thức tương tự cho theo tên khác với việc hiểu danh sách để lọc qua danh sách enum và lấy sự phù hợp trên các thuộc tính tên không?
jxramos

4
@jxramos thực hiện theo liên kết tài liệu trong câu trả lời của tôi, nó được đề cập rõ ràng ở đó. Sử dụng truy cập mục: Fruit['Orange'].
Martijn Pieters

Bingo, rất tuyệt vời! Tôi đã tìm kiếm các trang cho convert, coercecastnhưng không trúng bất cứ điều gì. Có vẻ như điều kỳ diệu đã xảy ra access enum members by name, use item access. Perfecto, cảm ơn rất nhiều, tôi sẽ xóa mã của tôi bằng cú pháp này.
jxramos

Tuyệt vời hơn nữa là tôi có thể sử dụng những thứ như "foobar" in Fruit.__members__để kiểm tra tư cách thành viên và thậm chí kéo ra Fruit.get( 'foobar', Fruit.Orange )để có được hương vị Enum mặc định đó. Mã của tôi trông đơn giản hơn rất nhiều, loại bỏ tất cả các giàn giáo tra cứu phụ kiện mà tôi đã đặt trước đó.
jxramos

1

Tôi nghĩ nó nói một cách đơn giản là chuyển đổi intgiá trị thành Enumbằng cách gọi EnumType(int_value), sau đó truy cập namevào Enumđối tượng:

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

Hoặc như một chức năng:

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

Tôi muốn một cái gì đó tương tự để tôi có thể truy cập một trong hai phần của cặp giá trị từ một tham chiếu duy nhất. Phiên bản vani:

#!/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))

Sự thất bại ném ra một ngoại lệ như mong đợi.

Một phiên bản mạnh mẽ hơn:

#!/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]))

Khi không được sử dụng đúng cách, điều này sẽ tránh tạo ra một ngoại lệ và thay vào đó, trả lại một chỉ báo lỗi. Một cách Pythonic khác để làm điều này là trả lại "Không có" nhưng ứng dụng cụ thể của tôi sử dụng trực tiếp văn bản.


Tại sao không chỉ định nghĩa __int____str__các phương thức trên một cá thể Enum?
Tim
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.