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

Guido van Rossum guido at python.org
Tue Apr 23 17:11:06 CEST 2013


I gotta say, I'm with Antoine here. It's pretty natural (also coming
from other languages) to assume that the class used to define the
enums is also the type of the enum values. Certainly this is how it
works in Java and C++, and I would say it's the same in Pascal and
probably most other languages.

This doesn't seem to matter much today, but various people are
thinking about adding optional type annotations to Python code (use
cases include hints for liters and better suggestions for IDEs). What
would be more natural than being able to write

class Color(Enum):
    RED = 1
    WHITE = 2
    BLUE = 3
    ORANGE = 4

class Bikeshed:
  def paint(self, hue: Color, opacity: int):
    ...

It would be awkward if the 'how' parameter had to be annotated with
Color.ValueClass, or if the type checkers had to learn to imply
.ValueClass if an attribute was labeled with an Enum type. Enums just
aren't special enough.

I find the docstring issue secondary.

--Guido


On Tue, Apr 23, 2013 at 7:57 AM, Antoine Pitrou <solipsis at pitrou.net> wrote:
> Le Wed, 24 Apr 2013 00:22:40 +1000,
> Nick Coghlan <ncoghlan at gmail.com> a écrit :
>>
>> Looking at the source
>> (https://bazaar.launchpad.net/~barry/flufl.enum/trunk/view/head:/flufl/enum/_enum.py),
>> I'm not seeing any fundamental technical issues with merging the Enum
>> and EnumValue class definitions, and then using "cls" where the
>> metaclass code currently uses "cls.__value_factory__"  (even for the
>> backwards compatible variant, the 2v3 metaclass issue isn't a problem,
>> you can just define a _BaseEnum class with the right metaclass using
>> the 2 & 3 compatible notation and inherit from that in a normal class
>> definition)
>>
>> However, there's one non-technical aspect of such a merger which does
>> concern me, which is the fact that you would lose the distinct
>> docstrings for the class and the values:
>
> You can work it around by making __doc__ a descriptor that behaves
> differently when called on a class or an instance. There is a slight
> metaclass complication because __doc__ is not writable on a class (but
> I suppose enums are already using a metaclass, so it's not much of an
> issue):
>
>
> class docwrapper:
>     def __init__(self, class_doc, instance_doc_func):
>         self.class_doc = class_doc
>         self.instance_doc_func = instance_doc_func
>
>     def __get__(self, instance, owner):
>         if instance is None:
>             return self.class_doc
>         else:
>             return self.instance_doc_func(instance)
>
> def instancedocwrapper(instance_doc_func):
>     class metaclass(type):
>         def __new__(meta, name, bases, dct):
>             dct['__doc__'] = docwrapper(dct['__doc__'],
>                                         instance_doc_func)
>             return type.__new__(meta, name, bases, dct)
>     return metaclass
>
> class D(metaclass=instancedocwrapper(
>            lambda self: "My instance:{}".format(self.x))):
>     """My beautiful, documented class."""
>     def __init__(self, x):
>         self.x = x
>
> class E(D):
>     """My magnificent subclass."""
>
> print("class doc:", D.__doc__)
> print("subclass doc:", E.__doc__)
> print("instance doc:", E(5).__doc__)
>
>
> Note that the builtin help() function always displays the class's
> __doc__, even when called on an instance which has its own __doc__.
>
> Regards
>
> Antoine.
>
>
> _______________________________________________
> Python-Dev mailing list
> Python-Dev at python.org
> http://mail.python.org/mailman/listinfo/python-dev
> Unsubscribe: http://mail.python.org/mailman/options/python-dev/guido%40python.org



-- 
--Guido van Rossum (python.org/~guido)


More information about the Python-Dev mailing list