[Python-ideas] Enums

Guido van Rossum guido at python.org
Thu Jul 28 16:58:36 CEST 2011


On Wed, Jul 27, 2011 at 8:57 PM, Nick Coghlan <ncoghlan at gmail.com> wrote:
> On Thu, Jul 28, 2011 at 12:21 PM, Guido van Rossum <guido at python.org> wrote:
>> I wish I could write
>>
>>  red = Enum(1)
>>
>> and it made the following true:
>>
>>  assert red == 1
>>  assert isinstance(red, int)  # a subclass
>>  assert str(red) == 'red'
>>
>> But we'd first need a non-hacky way for Enum() to know that it is
>> being assigned to something named 'red'. I have a few other use cases
>> for that as well, e.g. a Property class for App Engine that doesn't
>> require a metaclass to patch up the value.
>
> Yeah, a similar discussion came up in the context of defining
> namedtuple instances a while back (I don't recall if you were part of
> that conversation or not - IIRC, the thread started off on the topic
> of assignment decorators and ended up wandering down this road at some
> point)

I recall that, and I think I even contributed. But I agree we never
came up with anything acceptable.

> Most proposed solutions relied on some form of abuse of the def
> statement to define arbitrary objects that knew their own name. For
> example:
>
>  def red from namedvalue(1)  # Rather unnatural phrasing
>  def red as namedvalue(1)  # Phrasing is natural, but the name is on
> the wrong side of the 'as'
>  def red = namedvalue(1)  # Simple assignment may not suggest enough magic
>  def as red = namedvalue(1)  # Syntax soup!
>  as red def namedvalue(1)  # Just throw keywords at the screen and
> see if anything sticks
>  red def= namedvalue(1)  # An alternative inspired by augmented assignment
>  def red << namedvalue(1) # Arbitrary but suggestive
>
> A protocol would then be defined to make that work (regardless of the
> specific syntax). Either the actual call would be transformed into
> "namedvalue('red', 1)" (which has the virtue of working with existing
> objects like collections.namedtuple, but prevents provision of useful
> default behaviour) or else there would be a new protocol like
> "obj.__named__(name)", with a fallback to something like the
> NamedValue recipe if __named__ wasn't defined (which has the virtue of
> working with arbitrary objects as in "def red as 1", but requires
> adapter classes to work with existing APIs like namedtuple).
>
> The bikeshed was painted many different colours before the thread
> finally wound down without achieving any kind of resolution. I suspect
> this may end up being another PEP 308, where the only way it will ever
> happen is if *you* find a syntax you like (or are at least willing to
> tolerate in order to gain the functionality).

My current thinking would be that you could probably hack it in
CPython through bytecode inspection: find the STORE_FAST or
STORE_GLOBAL opcode right after the CALL_FUNCTION opcode, and see what
to name it assigns. This is of course terrible, depending on all sorts
of implementation stuff, but we might create a builtin function that
returns that variable name, assuming the scope is module-global or a
class scope. I know it sounds atrocious, but the alternative is
requiring extra mark-up and a hidden implied argument, which does not
sound good either. (Maybe extra mark-up could be required for the
proposed new builtin to work.)

> Adding an int-specific Enum class eliminates a lot of the use cases
> for a "named object" feature, which is the main reason I'm trying to
> hold out for the more general functionality - I still have hope that
> we'll strike on a syntax for named assignments that is clear enough
> and clean enough that none of the core devs actively oppose it.

I agree that named constants don't have to be ints -- though for most
types other than ints, my main requirement for enums (that they print
themselves nicely) is not an issue.

Regarding Ben Finney's requirement that enums primarily define unique
values and that enums from two different classes must compare unequal
even if their int values are equal, I really don't care about that.
You can use isinstance() if you want to check that.

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



More information about the Python-ideas mailing list