PEP 354: Enumerations in Python

Carl Banks invalidemail at aerojockey.com
Tue Feb 28 01:50:51 EST 2006


Ben Finney wrote:
> This PEP specifies an enumeration data type for Python.

-1 for this particular proposal as a builtin.  I feel it's not a great
design of something that isn't terribly useful to begin with.  +0 for
the standard library, only after a couple changes.  As I see it, this
whole proposal is a minor improvement over doing something like the
following, but too minor an improvement to add to the builtin
namespace:

MON = 'mon'
TUE = 'tue'
etc.

DAYS_OF_WEEK  = (MON,TUE,etc.)


[snip]
> It is possible to simply define a sequence of values of some other
> basic type, such as ``int`` or ``str``, to represent discrete
> arbitrary values.  However, an enumeration ensures that such values
> are distinct from any others, and that operations without meaning
> ("Wednesday times two") are not defined for these values.

Here's why I think it's not too useful to begin with: the benefits of
the enum you describe here are pretty weak.

It's a pretty weak case to have a dedicated builtin to prevent
duplicates in something that changes maybe once a month, as enums tend
to change rather slowly.  (At least, that's the way enums in other
languages are used, and the design you present here seems to suggest
you intend to use them that way as well.)  And frankly, a unit test or
assertion could check this.

As for preventing nonsensical operations on enum constants: good idea,
but let's face it: a decent programmer knows whether he or she's
dealing with a enum value or a piece of string data.  This is why I
said it's not terribly useful (as opposed to not useful at all).
Unfortunately, this proposal fails to prevent a nonsensical operation
in the case where it would be most useful to do so.


[snip]
> Enumerations with no values are meaningless.  The exception
> ``EnumEmptyError`` is raised if the constructor is called with no
> value arguments.

No strong feeling on this issue.  Probably no use for an empty enum,
but no harm either.


[snip]
> This allows the operation to succeed, evaluating to a boolean value::
>
>     >>> gym_night = Weekdays.wed
>     >>> gym_night < Weekdays.mon
>     False
>     >>> gym_night < Weekdays.wed
>     False
>     >>> gym_night < Weekdays.fri
>     True
>     >>> gym_night < 23
>     False
>     >>> gym_night > 23
>     True
>     >>> gym_night > "wed"
>     True
>     >>> gym_night > Grades.B
>     True

The nonsensical comparisions should throw value errors.  You say that
you want to get rid of operations that don't make sense, but it seems
misguided that we would get rid of multiplying by a integer (something
that's not likely to happen much at all) but retain comparison with
other types (something that's going to be much more common).

I realize that this is a thoughtful decision on your part, that you
have some reason for it and were not just blindly following the example
of other Python builtins.  However, IMHO, this design decision forsakes
the single most useful feature of an enum, and replaces it with
confusion.


[snip examples of use]

One thing I'd add is something like Weekdays.get_constant("wed").  I
realize that you can do this with getattr, but you can also do
getattr(Weekdays,"__dict__") with getattr, and you ought to have a
method that thows and exception if you try to access the __dict__
constant.

Also, it blesses the operation, so that people who are trying to access
the constant after reading its name from the database don't have to
feel guilty about using getattr.


[snip]
> Metaclass for creating enumeration classes
> ------------------------------------------
>
> The enumerations specified in this PEP are instances of an ``enum``
> type.  Some alternative designs implement each enumeration as its own
> class, and a metaclass to define common properties of all
> enumerations.
>
> One motivation for having a class (rather than an instance) for each
> enumeration is to allow subclasses of enumerations, extending and
> altering an existing enumeration.  A class, though, implies that
> instances of that class will be created;

How so?  This is true of classes with metaclass type, but using a
different metaclass suggests maybe it isn't like a regular class.  In
particular, constructing an instance could be a non-op; instead the
class creates it's own instances at definition time.  I don't see
anything that implies that a class can't do that.

> it is difficult to imagine
> what it means to have separate instances of a "days of the week"
> class, where each instance contains all days.

I don't understand what you're saying here.  It doesn't seem to me hard
to imagine that a class could create its own instances, but I'm not
sure if that's what you're talking about.

> This usually leads to
> having each class follow the Singleton pattern, further complicating
> the design.

Meh.  I don't feel too strongly about this, but I'd think an enum as a
class is better, because you can't (or, rather, oughtn't) compare
constants from different enums.  That's a logical demarcation of
classes.

Sorry if I was a little blunt here.  In the end, I really don't see the
problems that this enum addresses being all that common; it seems a lot
of work for minor benefit.


Carl Banks




More information about the Python-list mailing list