classification
Title: Expose an Enum object's serial number
Type: enhancement Stage: resolved
Components: Library (Lib) Versions: Python 3.5
process
Status: closed Resolution: rejected
Dependencies: Superseder:
Assigned To: ethan.furman Nosy List: barry, cool-RR, eli.bendersky, ethan.furman
Priority: normal Keywords:

Created on 2014-09-27 14:40 by cool-RR, last changed 2014-09-28 12:39 by eli.bendersky. This issue is now closed.

Messages (9)
msg227679 - (view) Author: Ram Rachum (cool-RR) * Date: 2014-09-27 14:40
I'd like Enum objects to expose their serial numbers. Currently it seems the only way to get this is `MyEnum._member_names_.index(my_enum.name)`, which is not cool because it's cumbersome and involves private variables.

Perhaps we can use `int(my_enum) == 7`? Or `my_enum.number == 7`? I'll be happy to make a patch if there's agreement about this.
msg227682 - (view) Author: Barry A. Warsaw (barry) * (Python committer) Date: 2014-09-27 14:58
On Sep 27, 2014, at 02:40 PM, Ram Rachum wrote:

>I'd like Enum objects to expose their serial numbers.

Can you please provide some motivating use cases?
msg227684 - (view) Author: Ram Rachum (cool-RR) * Date: 2014-09-27 14:59
Right now I want it for this: 

http://bugs.python.org/issue22504

Another use case I can think of is that if you store enum values in a database, you're probably using an int field and you'd want to easily convert between an enum and it's int value.
msg227691 - (view) Author: Barry A. Warsaw (barry) * (Python committer) Date: 2014-09-27 16:07
On Sep 27, 2014, at 02:59 PM, Ram Rachum wrote:

>Right now I want it for this: 
>
>http://bugs.python.org/issue22504

https://docs.python.org/3/library/enum.html#orderedenum

>Another use case I can think of is that if you store enum values in a
>database, you're probably using an int field and you'd want to easily convert
>between an enum and it's int value.

Why would you do that for non-int enum values?  There's lots of ways you could
store enum values in a database.   In Mailman, I use "regular" enums (not
IntEnums) but I use int values and store them in the database as INTEGERS.  I
could just as easily have used a string type and stored the enum member name
in the database.  Using subclasses and __members__ I think there's lots of
other viable alternatives that don't require changing the Enum API.
msg227694 - (view) Author: Ram Rachum (cool-RR) * Date: 2014-09-27 16:15
> https://docs.python.org/3/library/enum.html#orderedenum

As I said in the other ticket: I can easily use a subclass, but I think it's general enough functionality for it to be included in the standard library.

I could continue the discussion about databases, but it feels like a waste of time to me. The main principle is: If something has an important property (in this case an enum object's numerical value), it should be publicly exposed. Period. No need to spend hours discussing if and how that property will be used. They always end up getting used somehow-- The only question is whether the people using them need to obtain them through private variables for years until the developers finally understand that the property needs to be exposed publicly. If you want to go through that, be my guest.
msg227700 - (view) Author: Barry A. Warsaw (barry) * (Python committer) Date: 2014-09-27 16:46
On Sep 27, 2014, at 04:15 PM, Ram Rachum wrote:

>The main principle is: If something has an important property (in this case
>an enum object's numerical value), it should be publicly exposed.

I think this is a misunderstanding.  Only IntEnum members have a defined
numerical value.  Base Enum members have no inherent value semantics except
their existence.  The *syntax* of using integers for values is simply a
convention and one that's not even necessary for Enums to work properly.

Enum members are also defined to be unordered, so their serial number is
meaningless.  The fact that __members__ is an ordered dictionary is a
convenient implementation detail that's only exposed in the API to support
iteration over all members including aliases.

Let me say specifically that I am opposed to int() for coercion for
non-IntEnums because Enum values can be anything.  Likewise, member.number is
also a misnomer in this case:

>>> from enum import Enum
>>> class Colors(Enum):
...    a = 'a'
...    b = 'b'
...    c = 'c'
...
>>> Colors.a is Colors.b
False
>>> Colors.a is Colors.a
True

I think using IntEnums or a subclass to provide a convenient wrapper around
__members__ iteration is the only thing that makes sense here, but I still
don't think the stdlib needs to support it.  IMHO, this is a case where adding
to the public stdlib API would provide more complexity for little common
benefit.
msg227702 - (view) Author: Ram Rachum (cool-RR) * Date: 2014-09-27 17:04
> Enum members are also defined to be unordered, so their serial number is meaningless.

Are you sure? The documentation says "Enumerations support iteration, in definition order" and shows how `tuple(MyEnum)` outputs the values in definition order.


> Likewise, member.number is also a misnomer in this case:

I don't understand why it's a misnomer in the case you showed.
msg227738 - (view) Author: Ethan Furman (ethan.furman) * (Python committer) Date: 2014-09-27 21:55
Yes, we're sure.  ;)

Enums have a definition order to aid in the use-case of auto-numbering, and to make displays consistent.  However, the basic Enum type is unordered.

I do not see a serial number as being an intrinsic property of an enum -- outside of auto-numbering (also not available in the stdlib), what difference does it make what order it was defined in?  What matters is the name and the value.

If you want your enum to have a serial number you can easily add that functionality in.
msg227757 - (view) Author: Eli Bendersky (eli.bendersky) * (Python committer) Date: 2014-09-28 12:39
>> I could continue the discussion about databases, but it feels like a waste of time to me. The main principle is: If something has an important property (in this case an enum object's numerical value), it should be publicly exposed. Period. No need to spend hours discussing if and how that property will be used. They always end up getting used somehow-- The only question is whether the people using them need to obtain them through private variables for years until the developers finally understand that the property needs to be exposed publicly. If you want to go through that, be my guest.


This kind of attitude is not welcome in the core Python development community. Please keep the discussion courteous and stick to technical arguments.

FWIW I fully agree with Barry and Ethan here.
History
Date User Action Args
2014-09-28 12:39:32eli.benderskysetmessages: + msg227757
2014-09-27 21:55:00ethan.furmansetstatus: open -> closed
messages: + msg227738

assignee: ethan.furman
resolution: rejected
stage: resolved
2014-09-27 17:04:21cool-RRsetmessages: + msg227702
2014-09-27 16:46:11barrysetmessages: + msg227700
2014-09-27 16:15:44cool-RRsetmessages: + msg227694
2014-09-27 16:07:38barrysetmessages: + msg227691
2014-09-27 14:59:41cool-RRsetmessages: + msg227684
2014-09-27 14:58:15barrysetmessages: + msg227682
2014-09-27 14:54:01berker.peksagsetnosy: + barry, eli.bendersky, ethan.furman
2014-09-27 14:40:46cool-RRcreate