> What would you expect a Pythonic enum to look like?
>
> class Colour(Enum):
> red
> green
Hell no. I mean, even Go isn't that implicit, you still have to use the iota there. Anyway, this was considered, and you can see the reasons against it (standard explicit is better than implicit) here: http://www.python.org/dev/peps/pep-0435/#id38 > class Colour(Enum):
> red = 1
> green = 1
>
> Still, at least the mistake above would raise an error. Wouldn't it? Nope.
> That's a feature. If you mess up on the non-optional values then you get
> "aliases".
Aliases are a feature, like it or not. Having 100% unique enums would not actually be a good thing, seeing as how sometimes libraries support multiple names for the same enum value for backwards compatibility reasons.And if you do actually want to prevent the duplication problem, you can do this
class Color(Enum):
red, green, blue = range(3)
red_alias = red
Or alternatively, if having to specify how many values is too unimaginative for you, something like class Color(Enum):
red, green, blue, *_ = range(2**128)
red_alias = red
will also work. > So, you go hunting around in the docs to see if there's any way at all of
> avoiding the need to assign values manually. And there is:
>
> Colour = Enum('Colour', 'red, green')
>
> which suffers from the same problems as namedtuples:
> - you need to repeat the class name (in a string, which your IDE is
> unlikely to check)
> - the parameters are themselves in a string, which your IDE is
> unlikely to parse and provide in auto-complete (they can be separate
> strings, in a sequence, but that doesn't really help).
>
> Now if two potentially useful library classes are suffering from the same
> problems than isn't that a BIT OF A HINT to try make things better? Nope. It
> just shows how important it is to not be imaginative. Or something (crack).
It's true! IDEs don't deal well with meta-programming, and Python isn't Lisp! I don't love the namedtuple syntax particularly either, but what solution would you propose? There doesn't seem to be an easy way around it, afaict. > And it gets worse. What values do you think the above provides?
>
> Strings? That would makes sense (red = 'red'), in that it would display
> nicely and is going to provide easy to debug values. So nope.
Well, if we read the PEP (http://www.python.org/dev/peps/pep-0435/#id26): >>> class Shake(Enum):
... vanilla = 7
... chocolate = 4
... cookies = 9
... mint = 3
...
>>> for shake in Shake:
... print(shake)
...
Shake.vanilla
Shake.chocolate
Shake.cookies
Shake.mint
We see that printing an enum value gives the string representation, so I don't really think that it not defaulting to strings is that much of a problem. > Integers from zero? I mean that's how Python counts indices and there's "only
> one way to do it" so that's how Python counts enums, right? Nope.
I think I almost agree with you here. That said, zero does have a specific meaning in a boolean context, so I can see why they didn't go for it. > OK, so bit fields? That way we can do cool Colour.red | Colour.green and
> make the C programmers feel at home? Nope.
Aside from the whole never going to happen argument, I think this kind of shows the problem with doing this implicitly; whatever you do, it's not going to work for some people. > Give up? I'll tell you. It counts from 1. Presumably because it's really
> common to use the "if not enum" idiom. In someone's crack-addled dreams.
Hey, don't despair so much. You can always read the PEP and realise you can actually provide a dictionary as the second argument. So maybe you'd prefer def MyEnum(name, vals):
return Enum(name, {val: i for i, val in enumerate(vals)})
to have your enums start from 0. I should mention, this information is in the PEP: http://www.python.org/dev/peps/pep-0435/#id35