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

Serhiy Storchaka storchaka at gmail.com
Sat Apr 13 10:31:59 CEST 2013

On 12.04.13 15:55, Eli Bendersky wrote:
> The enumeration value names are available through the class members::
>      >>> for member in Colors.__members__:
>      ...     print(member)
>      red
>      green
>      blue

This is unnecessary because enumerations are iterable. 
Colors.__members__ is equal to [v.name for v in Colors] and the latter 
looks more preferable, because it does not use the magic method.

> The str and repr of the enumeration class also provides useful information::
>      >>> print(Colors)
>      <Colors {red: 1, green: 2, blue: 3}>
>      >>> print(repr(Colors))
>      <Colors {red: 1, green: 2, blue: 3}>

Does the enumeration's repr() use str() or repr() for the enumeration 
values? And same question for the enumeration's str().

> To programmatically access enumeration values, use ``getattr``::
>      >>> getattr(Colors, 'red')
>      <EnumValue: Colors.red [value=1]>

How to get the enumeration value by its value?

> Ordered comparisons between enumeration values are *not* supported.  Enums
> are
> not integers (but see `IntEnum`_ below)::

It's unexpected if values of the enumeration values have the natural 
order. And values of the enumeration values *should be* comparable 
("Iteration is defined as the sorted order of the item values").

> Enumeration values
> ------------------

There is some ambiguity in the term "enumeration values". On the one 
hand, it's the singleton instances of the enumeration class (Colors.red, 
Colors.gree, Colors.blue), and on the other hand it is their values (1, 
2, 3).

> But if the value *is* important,  enumerations can have arbitrary values.

Should enumeration values be hashable?

At least they should be comparable ("Iteration is defined as the sorted 
order of the item values").

> ``IntEnum`` values behave like integers in other ways you'd expect::
>      >>> int(Shape.circle)
>      1
>      >>> ['a', 'b', 'c'][Shape.circle]
>      'b'
>      >>> [i for i in range(Shape.square)]
>      [0, 1]

What is ``isinstance(Shape.circle, int)``? Does PyLong_Check() return 
true for ``IntEnum`` values?

> Enumerations created with the class syntax can also be pickled and
> unpickled::

This does not apply to marshalling, I suppose? Perhaps this is worth to 
mention explicitly. There may be some errors of incompatibility.

> The ``Enum`` class is callable, providing the following convenience API::
>      >>> Animals = Enum('Animals', 'ant bee cat dog')
>      >>> Animals
>      <Animals {ant: 1, bee: 2, cat: 3, dog: 4}>
>      >>> Animals.ant
>      <EnumValue: Animals.ant [value=1]>
>      >>> Animals.ant.value
>      1
> The semantics of this API resemble ``namedtuple``. The first argument of
> the call to ``Enum`` is the name of the enumeration.  The second argument is
> a source of enumeration value names.  It can be a whitespace-separated
> string
> of names, a sequence of names or a sequence of 2-tuples with key/value
> pairs.

Why the enumeration starts from 1? It is not consistent with namedtuple, 
in which indices are zero-based, and I believe that in most practical 
cases the enumeration integer values are zero-based.

> Use-cases in the standard library
> =================================

The Python standard library has many places where named integer 
constants used as bitmasks (i.e. os.O_CREAT | os.O_WRONLY | os.O_TRUNC, 
select.POLLIN | select.POLLPRI, re.IGNORECASE | re.ASCII). The proposed 
PEP is not applicable to these cases. Whether it is planned expansion of 
Enum or additional EnumSet class to aid in these cases?

More information about the Python-Dev mailing list