On 12 February 2013 19:26, Ethan Furman <ethan@stoneleaf.us> wrote:
On 02/12/2013 11:13 AM, Guido van Rossum wrote:
On Tue, Feb 12, 2013 at 10:31 AM, Ethan Furman <ethan@stoneleaf.us> wrote:
On 02/12/2013 10:08 AM, Guido van Rossum wrote:

I'm torn. I like the clean look of Tim's:

class Flag(Enum):
     RED, WHITE, BLUE

However, I don't like the magic needed for its implementation -- and
anybody who thinks they know Python pretty well and thinks about this
syntax for more than two seconds has to wonder how on earth it's done
(and the answer is pretty horrible). It is also pretty brittle to
depend on the lookup order -- and I suspect it will be prone to
masking other bugs (any typo in a name used in class-level code will
essentially generate a bogus new enum value).


It seems to me the point of an enum is to give names to an order, so why
would the lookup order be a problem?

Because the language requirement that the expressions in a tuple are
evaluated left-to-right is fairly weak. (There are other, similar
contexts where the order is not l2r.)
<snip>
Personally, I'd be fine with:

class Color(Enum):
   BLACK
   RED
   BLUE
   PURPLE

which avoids the l2r issue, and the repetitive use of val() (or whatever it's called).

Can you force people not to use:

class Color(Enum):
   BLACK, RED, BLUE, PURPLE

?
If I'm understanding the implementation, if you support one then you support the other. Hence the problem will still stand. That said, I'm not personally too worried about it.

As far as typos go, I don't think that's a new problem (it certainly isn't
for me, anyway ;) and my best defense is plenty of tests.

So with Tim's implementation, what happens here:

class Color(Enum):
   RED, GREEN, BLUE
   if sys.platform == 'win32':
     MAGENTA

and you happen to have no "import sys" in your module? The sys lookup
will succeed, create a new enum, and then you will get an error
something like this:

AttributeError: 'Enum' object has no attribute 'platform'

We could minimize that issue by requiring that enum names be ALLCAPS -- if something comes through that isn't, don't supply a value and let the AttributeError perculate up.

I think it's worse than that. I'm using Tim Delaney's code and I'm not really sure why it's doing what it's doing.

import sys

class Color(Enum):
   RED, GREEN, BLUE
   if sys.platform:
     MAGENTA

works and doesn't create Color.sys.

import sys

class Color(Enum):
   RED, GREEN, BLUE
   if sys:
     MAGENTA

works and _does_ create Color.sys.

So somehow there's enough magic to realise that if you are accessing an attribute, it's not going to be an enum. In other words, you don't need the ALLCAPS anyway. You might think "oh, good!". I think "oh noes!". It's way too magic for me.

The other idea:

class Color(Enum):
    values = "RED", "GREEN", "BLUE", "MAGENTA", "OTHER", "COLORS", "HERE", "TOO"

could be written

class Color(Enum):
    values = "RED GREEN BLUE MAGENTA OTHER COLORS HERE TOO".split()

so I'm OK with that, but then you're in the territory when you might as well go with the method Barry suggested.