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

Ethan Furman ethan at stoneleaf.us
Sat Apr 27 22:01:01 CEST 2013


On 04/27/2013 12:47 PM, Ethan Furman wrote:
> On 04/27/2013 11:45 AM, Steven D'Aprano wrote:
>> On 27/04/13 12:51, Ethan Furman wrote:
>>> On 04/26/2013 07:29 PM, Glenn Linderman wrote:
>> [...]
>>>> class Color( Enum ):
>>>>      Enum.__enumerationItems__(
>>>>             red=1,
>>>>             green=2,
>>>>             blue=3,
>>>>             )
>>>>      # other methods and assignments
>>>
>>> Or, if we go with the metaclass magic of re-using the class/type name (and who doesn't love metaclass magic??):
>>>
>>> class Color(Enum):
>>>      red = Color(1)
>>>      green = Color(2)
>>>      blue = Color 3)
>>>      look_ma_not_an_enum = 4
>>
>>
>> and from a later email:
>>
>>> The solution I like best is the helper class (called, originally enough, enum), and only those items get transformed:
>>>
>>> class Planet(IntEnum):
>>>     MERCURY = enum(1)
>>>     VENUS = enum(2)
>>>     EARTH = enum(3)
>>>     rough_pi = 3     # not transformed
>>
>>
>>
>> I'm sorry, but all these suggestions are getting the API completely backwards by making the common case harder than the
>> rare case.
>
> I should have made a better example.  In production code, doc strings can be priceless, so encouraging them seems like a
> good idea:
>
> class Planet(IntEnum):
>     MERCURY = enum(1, doc='closest planet to the sun (?)')
>     VENUS = enum(2, doc='the one with two names')
>     EARTH = enum(3, doc='home sweet home')
>     random_value = 42
>
> Of course, I think it would be even better if the name were 'Planet' instead of 'enum' as that would emphasize the fact
> that we are actually creating items of the enumeration inside the enumeration.  Kind of a shorthand for:
>
> class Planet(IntEnum):
>     def __init__(...):
>        ...
>     def blahblah(...):
>        ...
> Planet.MERCURY = Planet(...)
> Planet.VENUS = Planet(...)
> Planet.EARTH = Planet(...)
>
> which is the way I've done it for other classes in a similar situation.
>
>
>> We're creating an Enum, right? So the *common case* is to populate it with enum values. 99% of the time, enumerated
>> values will be all that we want from an enum. So that's the case that needs to be simple, not the rare case where you
>> have a non enum value in an enum class.
>>
>> The common case (enum values in an Enum class) should be easy, and the rare cases (ordinary class-like attributes)
>> possible.
>>
>> Explicit is better than implicit: if you want something to *not* be processed by the Enum metaclass, you have to
>> explicitly mark it as special. Dunders excepted, because they *are* special enough to break the rules. Since dunders are
>> reserved for Python, I'm happy with a rule that says that dunders cannot be set as enum values (at least not via the
>> metaclass). Otherwise, everything inside an Enum class is treated as an enum value unless explicitly flagged as not.
>
> While I agree that the common case should be simple, I also disagree that everything (especially functions) should
> easily be an enumerated value; the nice thing about being explicit as to which are the values (using 'enum' for example)
> is that it can also be used to capture functions in the rare case where that's what is desired.

Just a quick followup:

It seems to me that the *most* common case will be a simple name mapping, in which case one can do:

Planet = Enum._make('Planet', 'MERCURY VENUS EARTH')

and be done with it.

--
~Ethan~


More information about the Python-Dev mailing list