[Python-Dev] constant/enum type in stdlib

Nick Coghlan ncoghlan at gmail.com
Sat Nov 27 15:58:08 CET 2010


On Sun, Nov 28, 2010 at 12:01 AM, Michael Foord
<fuzzyman at voidspace.org.uk> wrote:
> Very interesting proposal (typed named values rather than just named
> constants). It doesn't handle flag values, which I would still like, but
> that only really makes sense for integers (sets can be OR'd but their
> representation is already understandable). Perhaps the integer named type
> could be special cased for that.
>
> Without the grouping functionality (associating a bunch of names together)
> you lose the 'from_name' functionality. Guido was in favour of this, and it
> is an obvious feature where you have grouping:
> http://mail.python.org/pipermail/python-dev/2010-November/105912.html
>
> """I expect that the API to convert between enums and bare ints should be
> i = int(e) and e = <enumclass>(i). It would be nice if s = str(e) and
> e = <enumclass>(s) would work too."""

Note that the "i = int(e)" and "s = str(e)" parts of Guido's
expectation do work (they are, in fact, the underling implementation
of the _raw() method), so an enum class would only be needed to
provide the other half of the equation. The named values have no
opinion on equivalence at all (they just defer to the parent class),
but change the rules for identity (which are always murky anyway,
since caching is optional even for immutable types).


> This wouldn't work with your suggested implementation (as it is). Grouping
> and mutable "named values" could be inefficient and have issues around
> identity / equality. Maybe restrict the API to the immutable primitives.

My proposal doesn't say anything about grouping at all - it's just an
idea for "here's a standard way to associate a canonical name with a
particular object, independent of the namespaces that happen to
reference that object".

Now, a particular *grouping* API may want to restrict itself in
various ways, but that's my point. We should be looking at a standard
solution for the ground level problem (i.e. the idea named_value
attempts to solve) and then let various 3rd party enum/name grouping
implementations flourish on top of that, rather than trying to create
an all-singing all-dancing "value grouping" API (which is going to be
far more intrusive than a simple API for "here's a way to give your
constants and important data structures names that show up in their
representations").

For example, using named_value as a primitive, you can fairly easily do:

class Namegroup:
    # Missing lots of niceties of a real enum class, but shows the idea
    # as to how a real implementation could leverage named_value
    def __init__(self, _groupname, **kwds):
        self._groupname = _groupname
        pattern = _groupname + ".{}"
        self._value_map = {}
        for k, v in kwds.items():
            attr = named_value(pattern.format(k), v)
            setattr(self, k, attr)
            self._value_map[v] = attr
    @classmethod
    def from_names(cls, groupname, *args):
        kwds = dict(zip(args, range(len(args))))
        return cls(groupname, **kwds)
    def __call__(self, arg):
        return self._value_map[arg]

silly = Namegroup.from_names("Silly", "FOO", "BAR", "BAZ")

>>> silly.FOO
Silly.FOO=0
>>> int(silly.FOO)
0
>>> silly(0)
Silly.FOO=0

named_value deals with all the stuff to do with pretending to be the
original type of object (only with an associated name), leaving the
grouping API to deal with issues of creating groups of names and
mapping between them and the original values in various ways.

Cheers,
Nick.

-- 
Nick Coghlan   |   ncoghlan at gmail.com   |   Brisbane, Australia


More information about the Python-Dev mailing list