2006-01-25 19:55:20 -05:00
|
|
|
|
PEP: 354
|
|
|
|
|
Title: Enumerations in Python
|
|
|
|
|
Version: $Revision$
|
|
|
|
|
Last-Modified: $Date$
|
|
|
|
|
Author: Ben Finney <ben+python@benfinney.id.au>
|
2013-05-10 08:45:20 -04:00
|
|
|
|
Status: Superseded
|
2006-01-25 19:55:20 -05:00
|
|
|
|
Type: Standards Track
|
|
|
|
|
Content-Type: text/x-rst
|
|
|
|
|
Created: 20-Dec-2005
|
|
|
|
|
Python-Version: 2.6
|
|
|
|
|
Post-History: 20-Dec-2005
|
2013-05-10 08:45:20 -04:00
|
|
|
|
Superseded-By: 435
|
2006-01-25 19:55:20 -05:00
|
|
|
|
|
|
|
|
|
|
2007-05-18 13:41:31 -04:00
|
|
|
|
Rejection Notice
|
|
|
|
|
================
|
|
|
|
|
|
|
|
|
|
This PEP has been rejected. This doesn't slot nicely into any of the
|
|
|
|
|
existing modules (like collections), and the Python standard library
|
2010-08-25 15:59:29 -04:00
|
|
|
|
eschews having lots of individual data structures in their own
|
2007-05-18 13:41:31 -04:00
|
|
|
|
modules. Also, the PEP has generated no widespread interest. For
|
|
|
|
|
those who need enumerations, there are cookbook recipes and PyPI
|
|
|
|
|
packages that meet these needs.
|
|
|
|
|
|
2022-01-21 06:03:51 -05:00
|
|
|
|
*Note: this PEP was superseded by* :pep:`435`, *which has been accepted in
|
2013-05-10 08:45:20 -04:00
|
|
|
|
May 2013.*
|
2007-05-18 13:41:31 -04:00
|
|
|
|
|
2006-01-25 19:55:20 -05:00
|
|
|
|
Abstract
|
|
|
|
|
========
|
|
|
|
|
|
|
|
|
|
This PEP specifies an enumeration data type for Python.
|
|
|
|
|
|
|
|
|
|
An enumeration is an exclusive set of symbolic names bound to
|
|
|
|
|
arbitrary unique values. Values within an enumeration can be iterated
|
|
|
|
|
and compared, but the values have no inherent relationship to values
|
|
|
|
|
outside the enumeration.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Motivation
|
|
|
|
|
==========
|
|
|
|
|
|
|
|
|
|
The properties of an enumeration are useful for defining an immutable,
|
|
|
|
|
related set of constant values that have a defined sequence but no
|
|
|
|
|
inherent semantic meaning. Classic examples are days of the week
|
|
|
|
|
(Sunday through Saturday) and school assessment grades ('A' through
|
|
|
|
|
'D', and 'F'). Other examples include error status values and states
|
|
|
|
|
within a defined process.
|
|
|
|
|
|
|
|
|
|
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.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Specification
|
|
|
|
|
=============
|
|
|
|
|
|
|
|
|
|
An enumerated type is created from a sequence of arguments to the
|
|
|
|
|
type's constructor::
|
|
|
|
|
|
|
|
|
|
>>> Weekdays = enum('sun', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat')
|
|
|
|
|
>>> Grades = enum('A', 'B', 'C', 'D', 'F')
|
|
|
|
|
|
|
|
|
|
Enumerations with no values are meaningless. The exception
|
|
|
|
|
``EnumEmptyError`` is raised if the constructor is called with no
|
|
|
|
|
value arguments.
|
|
|
|
|
|
|
|
|
|
The values are bound to attributes of the new enumeration object::
|
|
|
|
|
|
|
|
|
|
>>> today = Weekdays.mon
|
|
|
|
|
|
|
|
|
|
The values can be compared::
|
|
|
|
|
|
|
|
|
|
>>> if today == Weekdays.fri:
|
|
|
|
|
... print "Get ready for the weekend"
|
|
|
|
|
|
|
|
|
|
Values within an enumeration cannot be meaningfully compared except
|
|
|
|
|
with values from the same enumeration. The comparison operation
|
|
|
|
|
functions return ``NotImplemented`` [#CMP-NOTIMPLEMENTED]_ when a
|
|
|
|
|
value from an enumeration is compared against any value not from the
|
|
|
|
|
same enumeration or of a different type::
|
|
|
|
|
|
|
|
|
|
>>> gym_night = Weekdays.wed
|
|
|
|
|
>>> gym_night.__cmp__(Weekdays.mon)
|
|
|
|
|
1
|
|
|
|
|
>>> gym_night.__cmp__(Weekdays.wed)
|
|
|
|
|
0
|
|
|
|
|
>>> gym_night.__cmp__(Weekdays.fri)
|
|
|
|
|
-1
|
|
|
|
|
>>> gym_night.__cmp__(23)
|
|
|
|
|
NotImplemented
|
|
|
|
|
>>> gym_night.__cmp__("wed")
|
|
|
|
|
NotImplemented
|
|
|
|
|
>>> gym_night.__cmp__(Grades.B)
|
|
|
|
|
NotImplemented
|
|
|
|
|
|
|
|
|
|
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
|
|
|
|
|
|
|
|
|
|
Coercing a value from an enumeration to a ``str`` results in the
|
|
|
|
|
string that was specified for that value when constructing the
|
|
|
|
|
enumeration::
|
|
|
|
|
|
|
|
|
|
>>> gym_night = Weekdays.wed
|
|
|
|
|
>>> str(gym_night)
|
|
|
|
|
'wed'
|
|
|
|
|
|
|
|
|
|
The sequence index of each value from an enumeration is exported as an
|
|
|
|
|
integer via that value's ``index`` attribute::
|
|
|
|
|
|
|
|
|
|
>>> gym_night = Weekdays.wed
|
|
|
|
|
>>> gym_night.index
|
|
|
|
|
3
|
|
|
|
|
|
|
|
|
|
An enumeration can be iterated, returning its values in the sequence
|
|
|
|
|
they were specified when the enumeration was created::
|
|
|
|
|
|
|
|
|
|
>>> print [str(day) for day in Weekdays]
|
|
|
|
|
['sun', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat']
|
|
|
|
|
|
|
|
|
|
Values from an enumeration are hashable, and can be used as dict
|
|
|
|
|
keys::
|
|
|
|
|
|
|
|
|
|
>>> plans = {}
|
|
|
|
|
>>> plans[Weekdays.sat] = "Feed the horse"
|
|
|
|
|
|
|
|
|
|
The normal usage of enumerations is to provide a set of possible
|
|
|
|
|
values for a data type, which can then be used to map to other
|
|
|
|
|
information about the values::
|
|
|
|
|
|
|
|
|
|
>>> for report_grade in Grades:
|
|
|
|
|
... report_students[report_grade] = \
|
|
|
|
|
... [s for s in students if students.grade == report_grade]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Rationale -- Other designs considered
|
|
|
|
|
=====================================
|
|
|
|
|
|
|
|
|
|
All in one class
|
|
|
|
|
----------------
|
|
|
|
|
|
|
|
|
|
Some implementations have the enumeration and its values all as
|
|
|
|
|
attributes of a single object or class.
|
|
|
|
|
|
|
|
|
|
This PEP specifies a design where the enumeration is a container, and
|
|
|
|
|
the values are simple comparables. It was felt that attempting to
|
|
|
|
|
place all the properties of enumeration within a single class
|
|
|
|
|
complicates the design without apparent benefit.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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; 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. This usually leads to
|
|
|
|
|
having each class follow the Singleton pattern, further complicating
|
|
|
|
|
the design.
|
|
|
|
|
|
|
|
|
|
In contrast, this PEP specifies enumerations that are not expected to
|
|
|
|
|
be extended or modified. It is, of course, possible to create a new
|
|
|
|
|
enumeration from the string values of an existing one, or even
|
|
|
|
|
subclass the ``enum`` type if desired.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Values related to other types
|
|
|
|
|
-----------------------------
|
|
|
|
|
|
|
|
|
|
Some designs express a strong relationship to some other value, such
|
|
|
|
|
as a particular integer or string, for each enumerated value.
|
|
|
|
|
|
|
|
|
|
This results in using such values in contexts where the enumeration
|
|
|
|
|
has no meaning, and unnecessarily complicates the design. The
|
|
|
|
|
enumerated values specified in this PEP export the values used to
|
|
|
|
|
create them, and can be compared for equality with any other value,
|
|
|
|
|
but sequence comparison with values outside the enumeration is
|
|
|
|
|
explicitly not implemented.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Hiding attributes of enumerated values
|
|
|
|
|
--------------------------------------
|
|
|
|
|
|
|
|
|
|
A previous design had the enumerated values hiding as much as possible
|
|
|
|
|
about their implementation, to the point of not exporting the string
|
|
|
|
|
key and sequence index.
|
|
|
|
|
|
|
|
|
|
The design in this PEP acknowledges that programs will often find it
|
|
|
|
|
convenient to know the enumerated value's enumeration type, sequence
|
|
|
|
|
index, and string key specified for the value. These are exported by
|
|
|
|
|
the enumerated value as attributes.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Implementation
|
|
|
|
|
==============
|
|
|
|
|
|
|
|
|
|
This design is based partly on a recipe [#ENUM-RECIPE]_ from the
|
|
|
|
|
Python Cookbook.
|
|
|
|
|
|
|
|
|
|
The PyPI package ``enum`` [#ENUM-PACKAGE]_ provides a Python
|
|
|
|
|
implementation of the data types described in this PEP.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
References and Footnotes
|
|
|
|
|
========================
|
|
|
|
|
|
|
|
|
|
.. [#CMP-NOTIMPLEMENTED]
|
|
|
|
|
The ``NotImplemented`` return value from comparison operations
|
|
|
|
|
signals the Python interpreter to attempt alternative comparisons
|
|
|
|
|
or other fallbacks.
|
2008-10-02 08:40:49 -04:00
|
|
|
|
<http://docs.python.org/reference/datamodel.html#the-standard-type-hierarchy>
|
2006-01-25 19:55:20 -05:00
|
|
|
|
|
|
|
|
|
.. [#ENUM-RECIPE]
|
|
|
|
|
"First Class Enums in Python", Zoran Isailovski,
|
|
|
|
|
Python Cookbook recipe 413486
|
|
|
|
|
<http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/413486>
|
|
|
|
|
|
|
|
|
|
.. [#ENUM-PACKAGE]
|
|
|
|
|
Python Package Index, package ``enum``
|
|
|
|
|
<http://cheeseshop.python.org/pypi/enum/>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Copyright
|
|
|
|
|
=========
|
|
|
|
|
|
|
|
|
|
This document has been placed in the public domain.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
..
|
|
|
|
|
Local Variables:
|
|
|
|
|
mode: indented-text
|
|
|
|
|
indent-tabs-mode: nil
|
|
|
|
|
sentence-end-double-space: t
|
|
|
|
|
fill-column: 70
|
|
|
|
|
End:
|