2017-06-27 16 views
16

Tôi vừa phát hiện ra sự tồn tại của một lớp cơ sở Enum trong python và tôi đang cố gắng tưởng tượng nó có thể hữu ích cho tôi như thế nào.Làm thế nào để so sánh một chuỗi với một python enum?

Hãy nói rằng tôi xác định một tình trạng đèn giao thông:

from enum import Enum, auto 

class Signal(Enum): 
    red = auto() 
    green = auto() 
    orange = auto() 

Hãy nói rằng tôi nhận được thông tin từ một số hệ thống phụ trong chương trình của tôi, dưới hình thức của một chuỗi đại diện cho một tên màu, ví dụ brain_detected_colour = "red".

Làm cách nào để so sánh chuỗi này với tín hiệu đèn giao thông của tôi?

Rõ ràng, brain_detected_colour is Signal.redFalse, vì Signal.red không phải là một chuỗi.

Signal(brain_detected_colour) is Signal.red không thành công với ValueError: 'red' is not a valid Signal.

Trả lời

18

Một không tạo ra instance of an Enum. Cú pháp Signal(foo) được sử dụng để truy cập thành viên Enum theo giá trị, không được sử dụng khi chúng là auto().

Tuy nhiên người ta có thể sử dụng một chuỗi để access Enum members như người ta sẽ truy cập vào một giá trị trong một dict, sử dụng dấu ngoặc vuông:

Signal[brain_detected_colour] is Signal.red 

Một khả năng khác sẽ được so sánh chuỗi các name của một thành viên Enum:

# Bad practice: 
brain_detected_colour is Signal.red.name 

nhưng ở đây, chúng tôi không kiểm tra danh tính giữa các thành viên Enum, nhưng so sánh chuỗi, vì vậy nó là thực hành tốt hơn để sử dụng một thử nghiệm bình đẳng:

# Better practice: 
brain_detected_colour == Signal.red.name 

(So sánh danh tính giữa các chuỗi hoạt động nhờ string interning, tốt hơn là không nên dựa vào đó. Cảm ơn @mwchase và @Chris_Rands đã làm cho tôi nhận thức được rằng)

Tuy nhiên, khả năng khác sẽ được thiết lập một cách rõ ràng các giá trị thành viên như tên của họ khi tạo Enum:.

class Signal(Enum): 
    red = "red" 
    green = "green" 
    orange = "orange" 

(Xem this answer cho một phương pháp để có điều này tự động.)

Sau đó, Signal(brain_detected_colour) is Signal.red sẽ hợp lệ.

+6

Sử dụng 'is' trong' brain_detected_colour là Signal.red.name' là nguy hiểm; tốt hơn nên sử dụng '=='. – mwchase

+0

@mwchase Bạn có thể giải thích tại sao, để tôi có thể chỉnh sửa câu trả lời của mình và thêm giải thích? – bli

+4

Bạn đang dựa vào chuỗi thực tập, chi tiết thực hiện không rõ ràng http://guilload.com/python-string-interning/, không bao giờ sử dụng 'is' trừ khi bạn thực sự cần phải so sánh danh tính của các đối tượng –

5

Có thể có auto() trả lại tên của thành viên enum như giá trị của nó (đó là trong auto section of the docs :

>>> class AutoName(Enum): 
...  def _generate_next_value_(name, start, count, last_values): 
...   return name 
... 

>>> class Ordinal(AutoName): 
...  NORTH = auto() 
...  SOUTH = auto() 
...  EAST = auto() 
...  WEST = auto() 
... 

>>> list(Ordinal) 
[<Ordinal.NORTH: 'NORTH'>, <Ordinal.SOUTH: 'SOUTH'>, <Ordinal.EAST: 'EAST'>, <Ordinal.WEST: 'WEST'>] 

Điều này đòi hỏi phiên bản Python 3.6, hoặc aenum 2.0 (aenum hoạt động với Pythons cũ là 2.7).

Tiết lộ: Tôi là tác giả của Python stdlib Enum, các enum34 backport, và Advanced Enumeration (aenum) thư viện.

Các vấn đề liên quan