[Python-Dev] PEP 435 -- Adding an Enum type to the Python standard library

R. David Murray rdmurray at bitdance.com
Fri Apr 12 15:58:48 CEST 2013


On Fri, 12 Apr 2013 05:55:00 -0700, Eli Bendersky <eliben at gmail.com> wrote:
> Link to the PEP: http://www.python.org/dev/peps/pep-0435/ [it's also pasted
> fully below for convenience].

This looks great.  There's just one bit I don't understand.  I'm sure
it was discussed in the python-ideas thread, but the discussion of it
in the PEP does not provide any motivation for the decision.

> The ``Enum`` class supports iteration.  Iteration is defined as the
> sorted order of the item values::
> 
>     >>> class FiveColors(Enum):
>     ...     pink = 4
>     ...     cyan = 5
>     ...     green = 2
>     ...     blue = 3
>     ...     red = 1
>     >>> [v.name for v in FiveColors]
>     ['red', 'green', 'blue', 'pink', 'cyan']

[...]

> Ordered comparisons between enumeration values are *not* supported.  Enums
> are
> not integers (but see `IntEnum`_ below)::
> 
>     >>> Colors.red < Colors.blue
>     Traceback (most recent call last):
>     ...
>     NotImplementedError
>     >>> Colors.red <= Colors.blue
>     Traceback (most recent call last):
>     ...
>     NotImplementedError
>     >>> Colors.blue > Colors.green
>     Traceback (most recent call last):
>     ...
>     NotImplementedError
>     >>> Colors.blue >= Colors.green
>     Traceback (most recent call last):
>     ...
>     NotImplementedError

This is the part that I don't understand.  Enums *clearly* have an
ordering, since the iteration order is defined and stable.  Why should
I not be allowed to compare values from the same Enum type?  There are
certainly use cases where that is very useful.

To give you a concrete use case: consider response codes from a client
server application constructed the way typical internet protocols are.
We might have:

    class MyAppCode(Enum):

        ok = 200
        command_complete = 201
        status_response = 202
        help_response = 203
        service_ready = 204
        signoff_accepted = 205

        temporary_failure = 400
        service_not_available = 401
        server_error = 402
        out_of_resources = 403

        error = 500
        syntax_error = 501
        command_not_implemented = 502
        access_denied = 503
        resource_not_found = 504


It can be quite handy to be able to say things like:

    code = myapp.operation(opstring)
    if MyAppCode.temporary_failure < code < MyAppCode.error:
        myframework.requeue(opstring, code=code)
        return False
    elif code > MyAppCode.error:
        raise AppError(code)
    ....

In talking to an existing internet protocol it would be natural to use
IntEnum and this issue would not arise, but I have recently worked on
an application that had *exactly* the above sort of enumeration used
internally, when it would have been totally appropriate to use Enum rather
than IntEnum.  The ap has several places where an ordered comparison
against the enum is used to check if a code is in the error range or not.

--David


More information about the Python-Dev mailing list