How to compare Enums in Python?

As of Python 3.4, there is an Enum class.

I am writing a program where some constants have a certain order, and I wonder what path the most pythons are for comparing them:

 class Information(Enum): ValueOnly = 0 FirstDerivative = 1 SecondDerivative = 2 

Now there is a method that should compare the given information from information with various enumerations:

 information = Information.FirstDerivative print(value) if information >= Information.FirstDerivative: print(jacobian) if information >= Information.SecondDerivative: print(hessian) 

Direct comparison does not work with Enums, so there are three approaches, and I wonder which one is preferable:

Approach 1: Use Values:

 if information.value >= Information.FirstDerivative.value: ... 

Approach 2: Using IntEnum:

 class Information(IntEnum): ... 

Approach 3: Do not use enumerations at all:

 class Information: ValueOnly = 0 FirstDerivative = 1 SecondDerivative = 2 

Every approach works. Approach 1 is a bit more verbose, while approach 2 uses the not recommended IntEnum class, while approach 3 seems to be the same as it was before the addition of Enum.

I tend to use approach 1, but I'm not sure.

Thanks for the tips!

+7
python enums compare
source share
2 answers

You should always implement rich comparison operators if you want to use them with Enum . Using the functools.total_ordering class functools.total_ordering , you only need to implement the __eq__ method along with one order, for example. __lt__ . Since enum.Enum already implements __eq__ , this becomes even simpler:

 >>> import enum >>> from functools import total_ordering >>> @total_ordering ... class Grade(enum.Enum): ... A = 5 ... B = 4 ... C = 3 ... D = 2 ... F = 1 ... def __lt__(self, other): ... if self.__class__ is other.__class__: ... return self.value < other.value ... return NotImplemented ... >>> Grade.A >= Grade.B True >>> Grade.A >= 3 Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: unorderable types: Grade() >= int() 

Horrible, terrible, terrible things can happen with IntEnum . It was mainly included for backward compatibility; enumerations were implemented by subclassing int . From docs :

Enum is highly recommended for the vast majority of codes, since IntEnum breaks down some semantic promises of an enumeration (being comparable to integers and, therefore, transitivity to other unrelated enumerations). It should be used only in special cases where theres no other choice; for example, when integer constants are replaced with enumerations and backward compatibility is required with code that still expects integers.

Here is an example of why you do not want to do this:

 >>> class GradeNum(enum.IntEnum): ... A = 5 ... B = 4 ... C = 3 ... D = 2 ... F = 1 ... >>> class Suit(enum.IntEnum): ... spade = 4 ... heart = 3 ... diamond = 2 ... club = 1 ... >>> GradeNum.A >= GradeNum.B True >>> GradeNum.A >= 3 True >>> GradeNum.B == Suit.spade True >>> 
+10
source share

I have not met Enum before, so I looked at the document ( https://docs.python.org/3/library/enum.html ) ... and found OrderedEnum (section 8.13.13.2) Isn't that what you want ? From the doc:

 >>> class Grade(OrderedEnum): ... A = 5 ... B = 4 ... C = 3 ... D = 2 ... F = 1 ... >>> Grade.C < Grade.A True 
+1
source share

All Articles