Updates based on recent enhancements in flufl.enum + some clarifications.
More TODOs remain: importantly, the improved convenience/functional API.
This commit is contained in:
parent
e3654917be
commit
cb3c841bab
85
pep-0435.txt
85
pep-0435.txt
|
@ -27,6 +27,12 @@ and from their integer equivalents, supporting use cases such as storing
|
||||||
enumeration values in a database.
|
enumeration values in a database.
|
||||||
|
|
||||||
|
|
||||||
|
Decision
|
||||||
|
========
|
||||||
|
|
||||||
|
TODO: update decision here once pronouncement is made.
|
||||||
|
|
||||||
|
|
||||||
Status of discussions
|
Status of discussions
|
||||||
=====================
|
=====================
|
||||||
|
|
||||||
|
@ -263,39 +269,9 @@ that expect integers::
|
||||||
>>> int(Colors.blue)
|
>>> int(Colors.blue)
|
||||||
3
|
3
|
||||||
|
|
||||||
You can also convert back to the enumeration value by calling the Enum
|
You can also convert back to the enumeration value by indexing into the Enum
|
||||||
subclass, passing in the integer value for the item you want::
|
subclass, passing in the integer value for the item you want::
|
||||||
|
|
||||||
>>> Colors(1)
|
|
||||||
<EnumValue: Colors.red [int=1]>
|
|
||||||
>>> Colors(2)
|
|
||||||
<EnumValue: Colors.green [int=2]>
|
|
||||||
>>> Colors(3)
|
|
||||||
<EnumValue: Colors.blue [int=3]>
|
|
||||||
>>> Colors(1) is Colors.red
|
|
||||||
True
|
|
||||||
|
|
||||||
The Enum subclass also accepts the string name of the enumeration value::
|
|
||||||
|
|
||||||
>>> Colors('red')
|
|
||||||
<EnumValue: Colors.red [int=1]>
|
|
||||||
>>> Colors('blue') is Colors.blue
|
|
||||||
True
|
|
||||||
|
|
||||||
You get exceptions though, if you try to use invalid arguments::
|
|
||||||
|
|
||||||
>>> Colors('magenta')
|
|
||||||
Traceback (most recent call last):
|
|
||||||
...
|
|
||||||
ValueError: magenta
|
|
||||||
>>> Colors(99)
|
|
||||||
Traceback (most recent call last):
|
|
||||||
...
|
|
||||||
ValueError: 99
|
|
||||||
|
|
||||||
The Enum base class also supports getitem syntax, exactly equivalent to the
|
|
||||||
class's call semantics::
|
|
||||||
|
|
||||||
>>> Colors[1]
|
>>> Colors[1]
|
||||||
<EnumValue: Colors.red [int=1]>
|
<EnumValue: Colors.red [int=1]>
|
||||||
>>> Colors[2]
|
>>> Colors[2]
|
||||||
|
@ -304,10 +280,16 @@ class's call semantics::
|
||||||
<EnumValue: Colors.blue [int=3]>
|
<EnumValue: Colors.blue [int=3]>
|
||||||
>>> Colors[1] is Colors.red
|
>>> Colors[1] is Colors.red
|
||||||
True
|
True
|
||||||
|
|
||||||
|
The string name of the enumeration value is also accepted::
|
||||||
|
|
||||||
>>> Colors['red']
|
>>> Colors['red']
|
||||||
<EnumValue: Colors.red [int=1]>
|
<EnumValue: Colors.red [int=1]>
|
||||||
>>> Colors['blue'] is Colors.blue
|
>>> Colors['blue'] is Colors.blue
|
||||||
True
|
True
|
||||||
|
|
||||||
|
You get exceptions though, if you try to use invalid arguments::
|
||||||
|
|
||||||
>>> Colors['magenta']
|
>>> Colors['magenta']
|
||||||
Traceback (most recent call last):
|
Traceback (most recent call last):
|
||||||
...
|
...
|
||||||
|
@ -357,7 +339,6 @@ Enumeration values are hashable, so they can be used in dictionaries and sets::
|
||||||
red -> red delicious
|
red -> red delicious
|
||||||
green -> granny smith
|
green -> granny smith
|
||||||
|
|
||||||
|
|
||||||
IntEnum
|
IntEnum
|
||||||
-------
|
-------
|
||||||
|
|
||||||
|
@ -396,9 +377,12 @@ However they still can't be compared to ``Enum``::
|
||||||
>>> Shape.circle == Colors.red
|
>>> Shape.circle == Colors.red
|
||||||
False
|
False
|
||||||
|
|
||||||
For the vast majority of code, ``Enum`` is recommended. Only if a greater
|
For the vast majority of code, ``Enum`` is strongly recommended. Since
|
||||||
degree of interoperatility with integers is required and ``Enum`` does not
|
``IntEnum`` breaks some semantic promises of an enumeration (by being comparable
|
||||||
fit the bill, ``IntEnum`` should be used.
|
to integers, and thus by transitivity to other unrelated enumerations), it
|
||||||
|
should be used only in special cases where there's no other choice; for example,
|
||||||
|
when integer constants are replaced with enumerations and backwards
|
||||||
|
compatibility is required with code that still expects integers.
|
||||||
|
|
||||||
Pickling
|
Pickling
|
||||||
--------
|
--------
|
||||||
|
@ -410,10 +394,11 @@ Enumerations created with the class syntax can also be pickled and unpickled::
|
||||||
>>> Fruit.tomato is loads(dumps(Fruit.tomato))
|
>>> Fruit.tomato is loads(dumps(Fruit.tomato))
|
||||||
True
|
True
|
||||||
|
|
||||||
|
|
||||||
Convenience API
|
Convenience API
|
||||||
---------------
|
---------------
|
||||||
|
|
||||||
|
TODO: update to the new convenience API
|
||||||
|
|
||||||
You can also create enumerations using the convenience function ``make()``,
|
You can also create enumerations using the convenience function ``make()``,
|
||||||
which takes an iterable object or dictionary to provide the item names and
|
which takes an iterable object or dictionary to provide the item names and
|
||||||
values. ``make()`` is a module-level function.
|
values. ``make()`` is a module-level function.
|
||||||
|
@ -447,7 +432,6 @@ Proposed variations
|
||||||
Some variations were proposed during the discussions in the mailing list.
|
Some variations were proposed during the discussions in the mailing list.
|
||||||
Here's some of the more popular ones.
|
Here's some of the more popular ones.
|
||||||
|
|
||||||
|
|
||||||
Not having to specify values for enums
|
Not having to specify values for enums
|
||||||
--------------------------------------
|
--------------------------------------
|
||||||
|
|
||||||
|
@ -466,7 +450,6 @@ Cons: involves much magic in the implementation, which makes even the
|
||||||
definition of such enums baffling when first seen. Besides, explicit is
|
definition of such enums baffling when first seen. Besides, explicit is
|
||||||
better than implicit.
|
better than implicit.
|
||||||
|
|
||||||
|
|
||||||
Using special names or forms to auto-assign enum values
|
Using special names or forms to auto-assign enum values
|
||||||
-------------------------------------------------------
|
-------------------------------------------------------
|
||||||
|
|
||||||
|
@ -508,18 +491,24 @@ usages can be divided to two categories: user-code facing constants, and
|
||||||
internal constants.
|
internal constants.
|
||||||
|
|
||||||
User-code facing constants like ``os.SEEK_*``, ``socket`` module constants,
|
User-code facing constants like ``os.SEEK_*``, ``socket`` module constants,
|
||||||
decimal rounding modes, HTML error codes could benefit from being enums had
|
decimal rounding modes and HTML error codes could require backwards
|
||||||
they been implemented this way from the beginning. At this point, however, at
|
compatibility since user code may expect integers. ``IntEnum`` as described
|
||||||
the risk of breaking user code (that relies on the constants' actual values
|
above provides the required semantics; being a subclass of ``int``, it does not
|
||||||
rather than their meaning) such a change cannot be made. This does not mean
|
affect user code that expects integers, while on the other hand allowing
|
||||||
that future uses in the stdlib can't use an enum for defining new user-code
|
printable representations for enumeration values::
|
||||||
facing constants.
|
|
||||||
|
>>> import socket
|
||||||
|
>>> family = socket.AF_INET
|
||||||
|
>>> family == 2
|
||||||
|
True
|
||||||
|
>>> print(family)
|
||||||
|
SocketFamily.AF_INET
|
||||||
|
|
||||||
Internal constants are not seen by user code but are employed internally by
|
Internal constants are not seen by user code but are employed internally by
|
||||||
stdlib modules. It appears that nothing should stand in the way of
|
stdlib modules. These can be implemented with ``Enum``. Some examples
|
||||||
implementing such constants with enums. Some examples uncovered by a very
|
uncovered by a very partial skim through the stdlib: ``binhex``, ``imaplib``,
|
||||||
partial skim through the stdlib: ``binhex``, ``imaplib``, ``http/client``,
|
``http/client``, ``urllib/robotparser``, ``idlelib``, ``concurrent.futures``,
|
||||||
``urllib/robotparser``, ``idlelib``, ``concurrent.futures``, ``turtledemo``.
|
``turtledemo``.
|
||||||
|
|
||||||
In addition, looking at the code of the Twisted library, there are many use
|
In addition, looking at the code of the Twisted library, there are many use
|
||||||
cases for replacing internal state constants with enums. The same can be said
|
cases for replacing internal state constants with enums. The same can be said
|
||||||
|
|
Loading…
Reference in New Issue