[Python-Dev] Enum: subclassing? (original) (raw)

Ethan Furman ethan at stoneleaf.us
Thu May 2 00:11:20 CEST 2013


On 05/01/2013 02:48 PM, Eli Bendersky wrote:

> Am 01.05.2013 20:04, schrieb Eli Bendersky: > > > Actually, in flufl.enum, IntEnum had to define a magic valuefactory > > attribute, but in the current ref435 implementation this isn't needed, so > > IntEnum is just: > > > > class IntEnum(int, Enum): > > ''' > > Class where every instance is a subclass of int. > > ''' > > > > So why don't we just drop IntEnum from the API and tell users they should > do the > > above explicitly, i.e.: > > > > class SocketFamily(int, Enum): > > AFUNIX = 1 > > AFINET = 2 > > > > As opposed to having an IntEnum explicitly, this just saves 2 characters > > (comma+space), but is more explicit (zen!) and helps us avoid the > special-casing > > the subclass restriction implementation. > > Wait a moment... it might not be immediately useful for IntEnums (however, > that's because base Enum currently defines int which I find questionable), > but with current ref435 you can create your own enum base classes with your > own methods, and derive concrete enums from that. It also lets you have a > base class for enums and use it in isinstance(). > > If you forbid subclassing completely that will be impossible. > > > I'm not sure what you mean, Georg, could you clarify? > This works: > >>>> from ref435 import Enum >>>> class SocketFamily(int, Enum): > ... AFUNIX = 1 > ... AFINET = 2 > ... >>>> SocketFamily.AFINET > SocketFamily.AFINET [value=2] >>>> SocketFamily.AFINET == 2 > True >>>> type(SocketFamily.AFINET) > <Enum 'SocketFamily'> >>>> isinstance(SocketFamily.AFINET, SocketFamily) > True > > Now, with the way things are currently implemented, class IntEnum is just > syntactic sugar for above. Guido decided against allowing any kind of > subclassing, but as an implementation need we should keep some restricted form > to implement IntEnum. But is IntEnum really needed if the above explicit > multiple-inheritance of int and Enum is possible? Well, my point is that you currently don't have to inherit from int (or IntEnum) to get an int method on your Enum, which is what I find questionable. IMO conversion to integers should only be defined for IntEnums. (But I haven't followed all of the discussion and this may already have been decided.)

Good point. I think this may be just an artifact of the implementation - PEP 435 prohibits implicit conversion to integers for non-IntEnum enums. Since IntEnum came into existence, there's no real need for int-opearbility of other enums, and their values can be arbitrary anyway. Ethan - unless I'm missing something, int should probably be removed.

The reason int is there is because pure Enums should be using plain ints as their value 95% or more of the time, and being able to easily convert to a real int for either database storage, wire transmission, or C functions is a Good Thing.

IntEnum is for when the enum item must be a real, bonafide int in its own right, and the use case here is backwards compatibility with APIs that are already using real ints -- and this is really the only time IntEnum should be used).

The downside to IntEnum is you lose all Enum type protection; so if you don't need a real int, use a fake int, er, I mean, Enum, which can easily be int'ified on demand due to its handy dandy int method.



More information about the Python-Dev mailing list