[Python-Dev] Enumeration items: `type(EnumClass.item) is EnumClass` ?

Steven D'Aprano steve at pearwood.info
Mon Apr 29 20:24:59 CEST 2013


On 30/04/13 03:01, Guido van Rossum wrote:

> Oh dear, this is actually a mess. I don't want MoreColor.red and
> Color.red to be distinct objects, but then the isinstance() checks
> will become confusing. If we don't override isinstance(), we'll get
>
>    not isinstance(Color.red, MoreColor)
>    isinstance(MoreColor.yellow, Color)
>
> This would be pretty backwards.

Why is that backwards? MoreColor is a subclass of Color, so instances of MoreColor are instances of Color, but instances of Color are not instances of MoreColor. That's normal behaviour for subclasses. (All cats are mammals, but not all mammals are cats.)

The only "funny" thing about this is that enumeration values of a Enum are only instances of that Enum if they are declared inside that Enum, and as far as I'm concerned that's not especially funny at all. So:

Color declares red, so Color.red is a Color.

MoreColor does not declare red, it merely inherits it from Color, so MoreColor.red is Color.red which is not a MoreColor.


This leads to a simple rule:

Enum values are either instances of the enum they are defined in, or instances of the parent class they are inherited from.

If the user doesn't like that, they're free to not subclass Enums :-)



> I Ggoogled "enum subclassing" and found this StackOverflow article
> explaining why you can't subclass enums in Java:
> http://stackoverflow.com/questions/4604978/subclassing-an-enum which
> refers to this more elaborate answer:
> http://stackoverflow.com/questions/3427947/enumeration-inheritence-in-java/3428050#3428050

The first link says:

"And generally, a proper subclass is a specialization of its superclass."

and gives the Liskov Substitution Principle as the reason for prohibiting subclassing. LSP is a very useful principle, but it is not the only model for subclassing. That's why it's called a *principle* and not the Liskov Substitution *Law*.

(Yes, I stole that from Raymond Hettinger's talk on subclassing at PyCon.)

I think that the ability to extend enums with new ones, without duplicating code, is more important for enums than satisfying LSP. The common use-cases for enums do not lend itself to subtyping in the Liskov sense.

E.g. if I have a function that expects a Color red/blue/green enum, and I subclass it to give MoreColor yellow, I can't expect the function to suddenly recognise yellow. So I'm not going to use subclassing in this case, because it can't work.

But I will use subclassing to reuse values: if I have a function that expects red/blue/green/yellow, and red/blue/green are already defined in Color, I'll want to reuse them rather than duplicate them. Hence I will subclass Color specifically to extend it, not to specialise it.


The second link quotes:

"For the most part, extensibility of enums turns out to be a bad idea. It is confusing that elements of an extension type are instances of the base type and not vice versa."

Confusing for who, and why?

You're going to confuse *somebody* no matter what you do. Either:

- confuse people who try to subclass enums, and can't; or

- confuse people who try to subclass enums, and can, but then get confused by the result.





-- 
Steven


More information about the Python-Dev mailing list