In this case, the attributes are not ints.. so If you defined that class functions that took it's attributes would need to accept an int, and if I passed max-int or something it'd be up to your function to go figure out whether my argument was a valid value for Color.
The enum class gives you that stuff. The argument you'd expect would be instanceof(arg, Color) == True (I think that's how they did it) and if it was, you'd be assured that the value was a valid value for Color.
So you could do it yourself, sure.. but to get all the little benefits, you'd have to do more coding than naming a bunch of ints in a new class.. It's subtle though. Not a wild game-changer or anything :)
In addition to what famousactress said, you also get:
>>> Color.red
<Color.red: 1>
So when you print out an enumeration, you get its name instead of just the number. This can be a big deal for debugging e.g. OpenGL code, which has a lot of enumerations. Which of the following would you prefer?
IntEnum values behave like integers in other ways
you'd expect:
>>> int(Shape.circle)
1
>>> ['a', 'b', 'c'][Shape.circle]
'b'
>>> [i for i in range(Shape.square)]
[0, 1]
The syntax strikes me as somewhat strange. It requires writing out enum values (and thus avoiding duplicates or, for a cleaner look, just keeping them sorted), necessitating unnecessary effort when new values are added in the middle, and misleadingly implies that the enum values are merely class-level integer constants. I would have preferred a more explicit API that used a list of strings for the enumerators.
As an optional implementation that'd be nice, but this syntax I assume is meant to solve two problems:
1. Making the integral values of an enum clear and unchanged by re-ordering the names. If the integral values matter to you (because you serialize enums that way), then I would want them to be explicit.
2. The integer values of these enums aren't exclusive. Two enums can reference the same value.
That said, I agree a short hand for people who don't care seems reasonable, where the integers could be auto-assigned by definition order, or just all set to 0.
Adding new values in the middle is exactly why it needs to be explicit. If you're pickling them, for example, or otherwise recording them, you certainly care about the values. Auto-assignment is often convenient, but it certainly must never be the only way to do it.
I prefer the Michael Ford proposed syntax and would gladly port the implementation if possible.
Having to specify either an ordinal number like in BASIC of 1980 or have to specify symbols as strings looks dodgy to me.
I don't think that enums should have values (i.e. numbers).
Nearly every language does it that way but isn't that just because C originally implemented enums with numbers? Modern languages are much higher level.
Java enums don't have any numeric equivalent value, they are just objects, with textual names if you must convert them into something more primative.
Enum values don't have to be ints, they can have any value you want. The explicit values are there because Python's "explicit is better than implicit" zen, and the functional API gives you a way to create enums without assigning explicit values if you really want to.
I always thought the fact that Java enums don't have numeric values ended up being a nice idea, but a mistake.. specifically because .ordinal was still exposed, and ends up getting used by people who want to serialize the enum as something other than a string... .ordinal of course is affected by the order the enum is defined in, which is sketchy.
My memory could be a little faded on this though, I haven't coded in Java in a few years..
The user doesn't necessarily need to have access to the raw numbers I guess, but when it comes down to comparisons/branching etc, numbers are pretty much always going to be fastest and simplest.
And if they are going to be based on numbers underneath, why not let the user/coder/whatever have access to them?
It's also used to be sort of useful for serialization or storing them in a DB as they'd take up less space than a string, but these days that's not so important and I'd actually caution against it.
Basically you don't need it often, but when you do it's extremely useful.
Enumerations support iteration, in definition order:
>>> 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
Python's execution model sez that the class declaration is nothing more
than code that is exec'd in a dictionary. We know that Python dictionaries
do not perserve order, so why is this iteration in definition order
possible, barring modification to the interpreter or dict type ?
It's possible by using a __prepare__ method in the metaclass of Enum, which allows to return an essentially ordered dict for the __dict__ of enumeration classes.
There is an OrderedDict class in the collections module of standard library. Enums store their members in a special __members__ attribute, which is such an OrderedDict. See this section of the PEP: http://www.python.org/dev/peps/pep-0435/#duplicating-enum-me...
There's no need to modify the interpreter. Redefining __dict__ to support ordering would be enough, or perhaps defining a purpose-built __metaclass__[1].
There are a few things this proposal does that improves upon yours:
+ Enum values of different types are incomparable. This is widely seen as a good thing.
+ Enum values are instances of their Enum; this allows more flexibility in user code.
+ As a result of the above, you can have a dictionary without Enum values of two different types colliding.
+ Enum values print in a more friendly way. This is expected to help debugging.
+ To support the above, enum values know their own name. This is likely helpful both for debugging and for various introspection hacks.
+ Enums can be iterated over in a fixed order. This allows automated help systems and similar to maintain consistency between runs, improving user experience.
+ There's a lot more error checking provided to avoid cases like defining the same enum value twice.
But I understand your sentiment. We always enjoy smaller languages because it helps us keep them in our heads. But note that Enums aren't a new language feature -- this PEP simply adds another module to the standard library. The code your provide, flawed as it is, is still a pattern common to many different libraries, so it would be good to put it into the stdlib; but if we're doing that, might as well do it right, don't you think?
We expect the implementation will be committed in the next few weeks, and you'll be able to give it a try using Python's tip revision ("trunk"). It will actually _ship_ with Python 3.4
You could say that about a lot of things in Python. If you add a constant value as a class attribute, anyone using that class has the ability to change it, even if that would screw things up.
[+] [-] e1ven|13 years ago|reply
It seems like you declare these like any other class. So what's the difference between this, and creating a class full of ints?
If I have class Color: red = 1 blue = 2
etc, wouldn't I get the same thing?
Is the difference that you don't need to instantiate an instance of it?
I know I'm being dense, and I've read the PEP, but it's not quite clicking yet.
[+] [-] famousactress|13 years ago|reply
The enum class gives you that stuff. The argument you'd expect would be instanceof(arg, Color) == True (I think that's how they did it) and if it was, you'd be assured that the value was a valid value for Color.
So you could do it yourself, sure.. but to get all the little benefits, you'd have to do more coding than naming a bunch of ints in a new class.. It's subtle though. Not a wild game-changer or anything :)
[+] [-] dietrichepp|13 years ago|reply
[+] [-] pyre|13 years ago|reply
[+] [-] comex|13 years ago|reply
[+] [-] famousactress|13 years ago|reply
1. Making the integral values of an enum clear and unchanged by re-ordering the names. If the integral values matter to you (because you serialize enums that way), then I would want them to be explicit.
2. The integer values of these enums aren't exclusive. Two enums can reference the same value.
That said, I agree a short hand for people who don't care seems reasonable, where the integers could be auto-assigned by definition order, or just all set to 0.
[+] [-] oellegaard|13 years ago|reply
>>> Animal = Enum('Animal', 'ant bee cat dog') >>> Animal.ant <Animal.ant: 1>
That being said, I welcome enums - I made classes to basically represent an enum a bunch of times.
[+] [-] Tobu|13 years ago|reply
[+] [-] chrismorgan|13 years ago|reply
[+] [-] unknown|13 years ago|reply
[deleted]
[+] [-] maxerickson|13 years ago|reply
http://www.python.org/dev/peps/pep-0435/#functional-api
Having to throw in a " ".join(...) isn't that bad.
[+] [-] encoderer|13 years ago|reply
[+] [-] randlet|13 years ago|reply
[+] [-] gbin|13 years ago|reply
[+] [-] adrianmsmith|13 years ago|reply
Nearly every language does it that way but isn't that just because C originally implemented enums with numbers? Modern languages are much higher level.
Java enums don't have any numeric equivalent value, they are just objects, with textual names if you must convert them into something more primative.
[+] [-] brown9-2|13 years ago|reply
I think what you mean though is that in 99.9% of cases a user of a Java enum never needs to (or shouldn't) refer to the ordinal value.
[+] [-] eliben|13 years ago|reply
[+] [-] famousactress|13 years ago|reply
My memory could be a little faded on this though, I haven't coded in Java in a few years..
[+] [-] Nursie|13 years ago|reply
The user doesn't necessarily need to have access to the raw numbers I guess, but when it comes down to comparisons/branching etc, numbers are pretty much always going to be fastest and simplest.
And if they are going to be based on numbers underneath, why not let the user/coder/whatever have access to them?
[+] [-] kstrauser|13 years ago|reply
[+] [-] sp332|13 years ago|reply
[+] [-] mattmanser|13 years ago|reply
Examples from C#:
http://msdn.microsoft.com/en-us/library/vstudio/cc138362.asp...
It's also used to be sort of useful for serialization or storing them in a DB as they'd take up less space than a string, but these days that's not so important and I'd actually caution against it.
Basically you don't need it often, but when you do it's extremely useful.
[+] [-] marmaduke|13 years ago|reply
[+] [-] eliben|13 years ago|reply
[+] [-] shoyer|13 years ago|reply
[+] [-] saidajigumi|13 years ago|reply
[1] http://stackoverflow.com/a/6581949/183481
[+] [-] jjs|13 years ago|reply
[+] [-] pavpanchekha|13 years ago|reply
+ Enum values of different types are incomparable. This is widely seen as a good thing. + Enum values are instances of their Enum; this allows more flexibility in user code. + As a result of the above, you can have a dictionary without Enum values of two different types colliding. + Enum values print in a more friendly way. This is expected to help debugging. + To support the above, enum values know their own name. This is likely helpful both for debugging and for various introspection hacks. + Enums can be iterated over in a fixed order. This allows automated help systems and similar to maintain consistency between runs, improving user experience. + There's a lot more error checking provided to avoid cases like defining the same enum value twice.
But I understand your sentiment. We always enjoy smaller languages because it helps us keep them in our heads. But note that Enums aren't a new language feature -- this PEP simply adds another module to the standard library. The code your provide, flawed as it is, is still a pattern common to many different libraries, so it would be good to put it into the stdlib; but if we're doing that, might as well do it right, don't you think?
[+] [-] unknown|13 years ago|reply
[deleted]
[+] [-] jayflux|13 years ago|reply
Didn't Python 3 do more removing/tidying up than actually adding of stuff?
[+] [-] nilsbunger|13 years ago|reply
[+] [-] eliben|13 years ago|reply
[+] [-] tshepang|13 years ago|reply
[+] [-] morpher|13 years ago|reply
[+] [-] nobodysfool|13 years ago|reply
I.E. If my database takes a 'Sex' parameter, with Male as 1, Female as 2, Unknown as 3, Both as 4 - I'd use an enum like so:
Looks like I can't do that with this enum class. Well, I suppose I'd have to do it like so: not very sexy...[+] [-] bsimpson|13 years ago|reply
[+] [-] herge|13 years ago|reply
[+] [-] yen223|13 years ago|reply
[+] [-] eliben|13 years ago|reply
It's still useful to have mnemonic names for special values, with nice string representations and some guarantees on what is equal to what.
[+] [-] oellegaard|13 years ago|reply
[+] [-] unknown|13 years ago|reply
[deleted]
[+] [-] lmm|13 years ago|reply
[+] [-] dvanduzer|13 years ago|reply
http://docs.python.org/3/reference/datamodel.html#objects-va...
[+] [-] pyre|13 years ago|reply
[+] [-] ajanuary|13 years ago|reply
Anyone know the motivation for this? Seems like a source of frustration to me.
[+] [-] unknown|13 years ago|reply
[deleted]
[+] [-] dschep|13 years ago|reply
[+] [-] Toshio|13 years ago|reply
[1] http://bazaar.launchpad.net/~barry/flufl.enum/trunk/view/hea...
[+] [-] eliben|13 years ago|reply
We may create a almost-compliant back-port for 2.7 as an external library though