Coder Social home page Coder Social logo

Comments (14)

ethanfurman avatar ethanfurman commented on July 17, 2024 2

One of the big concerns for enums are their creation times. We'll need performance numbers with and without the ABC addition.

from cpython.

ygale avatar ygale commented on July 17, 2024 1

We have this in enum.py:

EnumMeta = EnumType         # keep EnumMeta name for backwards compatibility
class Enum(metaclass=EnumType):
    ...

So in my example, we have that Flowers.ROSES is an instance of the class Flowers, which is a subclass of Enum. But we have type(Flowers) is EnumType - which is a bit weird, because usually the type of class objects is type. That allows the Flowers class object to have methods that provide enum features. When defining Flowers with functional syntax in typed Python, you would write Flowers: EnumType = Enum('Flowers', ...).

After this change, Flowers is also a descendant of ABCMeta. The effect of that is that there are a few ABC-related members (such as _abc_impl) that are only used when you use it as a metaclass to create an ABC or a subclass of an ABC. To use an ABC as a mixin for the enum - that is exactly what you need. In any other case, they are not used.

from cpython.

nineteendo avatar nineteendo commented on July 17, 2024 1

Thanks, I think EnumType is a confusing name for the meta class of Enum. EnumType sounds like EnumType = Enum to me, like all types in types.

Flowers.ROSES is an instance of Flowers, which is a subclass of Enum. Enum is an instance of EnumType, which is a subclass of ABCMeta.

from cpython.

sobolevn avatar sobolevn commented on July 17, 2024 1

I think that we should not complicate EnumType which is very complex as it is.

But, instead you can solve this by adding several lines to your code:

>>> import abc
>>> import enum
>>> class A(abc.ABC): ...
... 
>>> class MyEnum(A, enum.Enum):
...     a = A()
...     
Traceback (most recent call last):
  File "<python-input-3>", line 1, in <module>
    class MyEnum(A, enum.Enum):
        a = A()
TypeError: metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases

Solution:

>>> class ABCEnum(abc.ABCMeta, enum.EnumType):
...     ...
...     
>>> class MyEnum(A, enum.Enum, metaclass=ABCEnum):
...     a = A()
...     
>>> MyEnum.a
<MyEnum.a: <__main__.A object at 0x105210f80>>

from cpython.

ethanfurman avatar ethanfurman commented on July 17, 2024 1

@ygale Using self.ROSES is the preferred way; I was stuck in a purist mode when I made those arguments, but practicality won out in the end (thank goodness!).

from cpython.

ethanfurman avatar ethanfurman commented on July 17, 2024 1

In addition to enum creation time, Python start-up time is a concern.

from cpython.

nineteendo avatar nineteendo commented on July 17, 2024

This sounds like it could break user code.

from cpython.

ygale avatar ygale commented on July 17, 2024

@nineteendo Can you come up with a case where it would break user code? It seems pretty safe to me.

If you do not use an ABC-derived mixin with Enum, the only change is a few harmless additional ABC-related members of the metaclass for an Enum. None of the ABC machinery will fire, and the resulting Enum class itself will be unchanged.

If you do use an ABC-derived mixin, how did you get it to work until now? If you used the @_simple_enum decorator, nothing changed and it will still work. If you used the simple work-around of defining an empty metaclass that inherits from both ABCMeta and EnumType, everything will still work. Same if you used one of the older workarounds where you define a custom metaclass with some methods and use that.

If you did some really deep metaclass hacking that modifies the way ABCs work AND you didn't override all of the metaclass methods AND you use your custom ABC machinery together with an Enum class, then this might require some tweaking. It seems to me that this very specialized corner case for very advanced users is a small cost compared to the surprising common failure we are fixing.

If you can construct a plausible concrete case where this might actually break user code, it's likely we can tweak this solution to provide backwards compatibility.

from cpython.

nineteendo avatar nineteendo commented on July 17, 2024

Ah sorry, I thought you meant to make EnumType a subclass of EnumMeta (whatever that means).
Technically EnumType is now an instance (not a subclass) of ABCMeta by making EnumMeta a subclass of ABCMeta.
A class is an instance of a meta class.

from cpython.

ygale avatar ygale commented on July 17, 2024

Agreed. I am guessing that the motivation behind the name change was that it is now also used as a type in typed Python.

from cpython.

ygale avatar ygale commented on July 17, 2024

@sobolevn We are not complicating EnumType at all. it's essentially a simple one-line change. And on the contrary, I think forcing users to hack on metaclasses for a simple use case is not reasonable.

from cpython.

ygale avatar ygale commented on July 17, 2024

One of the big concerns for enums are their creation times. We'll need performance numbers with and without the ABC addition.

Yep, will do. I'm also considering disabling this for construction via the @_simple_enum decorator. But let's see what the benchmarks say.

I found some discussion (in which you participated) in #93910. Any other pointers?

from cpython.

ygale avatar ygale commented on July 17, 2024

Another point that arises from #93910. In my example in the description, and also in my tests, I implemented the color() method in what I thought was the simplest way: match self ... case self.ROSES .... But that uses the Color.RED.RED behavior which now I see is controversial. I'll change them to match on self.name.

from cpython.

ygale avatar ygale commented on July 17, 2024

@ethanfurman OK. While I'm at it, I might as well profile member access time as well.

from cpython.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.