GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — Change in semantics and much worse performance for enum members. · Issue #93910 · python/cpython

Change in semantics and much worse performance for enum members. #93910

New issue
Copy link
New issue
Copy link
Closed
Closed
Change in semantics and much worse performance for enum members.#93910
Copy link
Assignees
ethanfurman
Labels
performancePerformance or resource usagePerformance or resource usagestdlibStandard Library Python modules in the Lib/ directoryStandard Library Python modules in the Lib/ directory

Description

@markshannon
markshannon
opened on Jun 16, 2022
Issue body actions

Given the enum:

class Colours(Enum):
    RED = 1

In Python 3.9 and 3.10:

>>> Colours.__dict__["RED"] is Colours.RED
True
>>> Colours.RED.RED
<Colours.RED: 1>

In Python 3.11:

>>> Colours.__dict__["RED"] is Colours.RED
False
>>> Colours.RED.RED
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/mark/repos/cpython/Lib/enum.py", line 198, in __get__
    raise AttributeError(
    ^^^^^^^^^^^^^^^^^^^^^
AttributeError: <enum 'Colours'> member has no attribute 'RED'

While these might seem like minor semantic changes, there is also a large performance impact.
Lookup of Colours.RED is simple and efficient in 3.10, but involves a lot of indirection and dispatching through the enum.property class in 3.11.
The performance impact is likely to get worse in 3.12, as we optimize more kinds of attributes.

Introduced in c314e60, I believe.

@pablogsal
@ethanfurman

Linked PRs

  • gh-93910: [Enum] remove member.member deprecation #103236
  • [3.11] gh-93910: [Enum] remove member.member deprecation (GH-103236) #103299

Activity

Next
  1. markshannon
    added
    type-bugAn unexpected behavior, bug, or errorAn unexpected behavior, bug, or error
    3.11only security fixesonly security fixes
    3.12only security fixesonly security fixes
    deferred-blocker
    performancePerformance or resource usagePerformance or resource usage
    on Jun 16, 2022
  2. AlexWaygood
    added
    stdlibStandard Library Python modules in the Lib/ directoryStandard Library Python modules in the Lib/ directory
    on Jun 16, 2022
  3. ethanfurman
    removed
    type-bugAn unexpected behavior, bug, or errorAn unexpected behavior, bug, or error
    deferred-blocker
    on Jun 22, 2022
  4. ethanfurman commented on Jun 22, 2022

    @ethanfurman
    ethanfurman
    on Jun 22, 2022
    Member
    More actions

    Those changes are intentional, and remedy an issue present since 3.5. As for performance, the work @markshannon and others have done has already had a considerable impact on making enum faster in 3.12.

    Reacted by GhaziGithub
  5. ethanfurman
    self-assigned this
    on Jun 22, 2022
  6. markshannon commented on Jun 22, 2022

    @markshannon
    markshannon
    on Jun 22, 2022
    MemberAuthor
    More actions

    What issue does the change remedy?

    I'm puzzled by your claim that the work we've done has sped up enums for 3.12? It hasn't. Without c314e60, it would have.

  7. markshannon commented on Jun 22, 2022

    @markshannon
    markshannon
    on Jun 22, 2022
    MemberAuthor
    More actions

    It looks like the change in Colours.RED.RED has been brought up before: #87328
    Failing on 3.11 seems to be in violation of PEP 387. A warning should be issued until 3.12.

    What I don't understand is why this change is necessary at all.
    What benefits does it bring? Accessing class attributes from instances is fairly universal, why should enums be special?

  8. ethanfurman commented on Jun 22, 2022

    @ethanfurman
    ethanfurman
    on Jun 22, 2022
    Member
    More actions

    The rudimentary timings I did on my system for member access showed enums steadily getting faster over the releases, with a big jump in performance between 3.11 and 3.12.

    The Colors.RED.RED behavior was illegal/missing in 3.4, added in 3.5 for performance (but warned against), and SC permission recieved for skipping the programmatic warning in 3.11

    Enums are special, and this change brings them back into line with the original, intended, specification.

    Reacted by Lewis Gaul
  9. markshannon commented on Jun 24, 2022

    @markshannon
    markshannon
    on Jun 24, 2022
    MemberAuthor
    More actions

    The performance of enum lookup is much slower than it should be in 3.11.
    It would be a shame to have to advise people not to use enums if they care about performance.

    The SC permission pertains to changes in repr(), str(), and format(), AFAICT. No mention is made of the the change in semantics of attribute lookup and performance.

    @warsaw Could you confirm?

  10. markshannon commented on Jun 24, 2022

    @markshannon
    markshannon
    on Jun 24, 2022
    MemberAuthor
    More actions

    I'm seeing an approx x9 slowdown on attribute access.

    class Color(Enum):
        RED = "Red"
        BLUE = "Blue"
        GREEN = "Green"
    
    class FastColor:
        RED = Color.RED
        BLUE = Color.BLUE
        GREEN = Color.GREEN
        
    def f():
        for _ in range(1000):
            Color.RED
            Color.BLUE
            Color.GREEN
            
    import timeit
    print(timeit.timeit('f()', number=10000, globals=globals()))
    
    Color = FastColor
    print(timeit.timeit('f()', number=10000, globals=globals()))

    With an optimized, but non pgo, no lto, build.

    0.8739701807498932
    0.09454824822023511
    
  11. 99 remaining items

  12. ethanfurman commented on Apr 4, 2023

    @ethanfurman
    ethanfurman
    on Apr 4, 2023
    Member
    More actions

    The enum.property descriptor is complex because it's handling three different cases:

    1. attribute is a member (i.e. Color.BLUE)
    2. attribute is a non-member (i.e. Color.BLUE.name)
    3. attribute is both (i.e. Fields.name (member) and Fields.name.name (name of member))

    The current enum code uses an enum.property for all members; the PR I asked you to benchmark returns to the behavior of only using an enum.proprtey in cases where both a member and a non-member attribute share the same name (i.e. the name in Fields.name and Fields.name.name) -- in other words, with that PR the vast majority of enums would have their members stored directly in the class __dict__. It also restores the Color.RED.RED behavior, but if the performance gain is substantial then practicality beats purity. For that matter, even if it isn't I have been convinced the member.member access is a good idea, and will finish the PR and merge it.

    Reacted by James Hilton-Balfe
  13. ethanfurman
    added 3 commits that reference this issue on Apr 6, 2023

    gh-93910: [Enum] remove member.member deprecation (GH-103236)

    4ec8dd1

    [3.11] pythongh-93910: [Enum] remove member.member deprecation (pyth…

    e573165

    [3.11] gh-93910: [Enum] remove member.member deprecation (GH-103236) (G…

    58e330a
  14. gaogaotiantian
    added a commit that references this issue on Apr 8, 2023

    pythongh-93910: [Enum] remove member.member deprecation (pythonGH-103236

    b536c34
  15. warsaw
    added a commit that references this issue on Apr 11, 2023

    pythongh-93910: [Enum] remove member.member deprecation (pythonGH-103236

    ac56605
  16. JelleZijlstra commented on May 22, 2023

    @JelleZijlstra
    JelleZijlstra
    on May 22, 2023
    Member
    More actions

    This is still marked as a "deferred blocker", but I'm not really clear on what the concrete item is that is still a blocker. Would it be better to close this very long issue and open a new one for any concrete problem that still needs fixing?

    Reacted by Erlend E. Aasland
  17. Yhg1s
    removed
    deferred-blocker
    3.12only security fixesonly security fixes
    on Jul 11, 2023
  18. AlexWaygood
    added this to enum issueson Jul 21, 2023
  19. ethanfurman commented on Dec 20, 2023

    @ethanfurman
    ethanfurman
    on Dec 20, 2023
    Member
    More actions

    I'm pretty sure this has been resolved. Please open a new issue if anything still needs handling.

  20. ethanfurman
    closed this as completedon Dec 20, 2023
  21. github-project-automation
    moved this from In Progress to Done in Release and Deferred blockers 🚫on Dec 20, 2023
  22. github-project-automation
    moved this to Done in enum issueson Dec 20, 2023
  23. parthea
    added a commit that references this issue on Nov 24, 2025

    fix: Add support for Python 3.11 (#329)

    bad8051
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

  • @ethanfurman
    ethanfurman

Labels

performancePerformance or resource usagePerformance or resource usagestdlibStandard Library Python modules in the Lib/ directoryStandard Library Python modules in the Lib/ directory

Projects

  • Release and Deferred blockers 🚫
    Status
    Done
    Show more project fields
  • enum issues
    Status
    Done
    Show more project fields

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions

You are visitor 01402503 — GeezerVison does not store the pages you look up.
Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.