Comparing Python enums to Java, was: How much sanity checking is required for function inputs?

Ian Kelly ian.g.kelly at gmail.com
Sun Apr 24 14:55:28 EDT 2016


On Sun, Apr 24, 2016 at 10:04 AM, Ethan Furman <ethan at stoneleaf.us> wrote:
> On 04/24/2016 08:20 AM, Ian Kelly wrote:
>> * Java doesn't have the hokey notion of enum instances being distinct
>> from their "value". The individual enum members *are* the values.
>> Whereas in Python an enum member is an awkward class instance that
>> contains a value of some other type. Python tries to get away from the
>> C-like notion that enums are ints by making the enum members
>> non-comparable, but then gives us IntEnum as a way to work around it
>> if we really want to. Since Java enums don't depend on any other type
>> for their values, there's nothing inviting the user to treat enums as
>> ints in the first place.
>
>
> How does Java share enums with other programs, computers, and/or languages?

Java enums are serializable using the name. If you need it to be
interoperable with other languages where they're int-based, then you
could attach that value as a field. But that would just be data; you
wouldn't be making that value an integral part of the Java enum just
because some other language does it that way.

>> Because they have the same "value", instead of creating a separate
>> member, COUNTER_EARTH gets defined as an alias for EARTH. To work
>> around this, one would have to add a third argument to the above to
>> pass in an additional value for the sole purpose of distinguishing (or
>> else adapt the AutoNumber recipe to work with this example). This
>> example is a bit contrived since it's generally not likely to come up
>> with floats, but it can easily arise (and in my experience frequently
>> does) when the arguments are of more discrete types. It's notable that
>> the Java enum docs feature this very same example but without this
>> weakness. [2]
>
>
> One reason for this is that Python enums are lookup-able via the value:
>
>>>> Planet(9.80265274333129)
> Planet.EARTH
>
> Do Java enums not have such a feature, or this "feature" totally unnecessary
> in Java?

It's unnecessary. If you want to look up an enum constant by something
other than name, you'd provide a static method or mapping.

I'd argue that it's unnecessary in Python too for the same reason. But
as long as Python enums make a special distinction of their value,
there might as well be a built-in way to do it.

> I could certainly add a "no-alias" feature to aenum.  What would be the
> appropriate value-lookup behaviour in such cases?
>
> - return the first match
> - return a list of matches
> - raise an error
> - disable value-lookups for that Enum

Probably the third or fourth, as I think that value lookup would
generally not be useful in such cases, and it can be overridden if
desired.

> Cool.  The stdlib Enum (and therefore the enum34 backport) is unlikely to
> change much.  However, aenum has a few fun things going on, and I'm happy to
> add more:
>
> - NamedTuple (metaclass-based)
> - NamedConstant (no aliases, no by-value lookups)
> - Enum
>   - magic auto-numbering
>       class Number(Enum, auto=True):
>          one, two, three
>          def by_seven(self):
>              return self.value * 7
>   - auto-setting of attributes
>        class Planet(Enum, init='mass radius'):
>              MERCURY = 3.303e23, 2.4397e6
>              EARTH = 5.976e24, 6.37814e6
>              NEPTUNE = 1.024e26, 2.4746e7
>        --> Planet.EARTH.mass
>        5.976e24

Neat!



More information about the Python-list mailing list