Skip to content

[Enum] Deprecate member.member access with removal in 3.14 #95077

Description

@ethanfurman

Accessing one enum member from another was originally forbidden, but added later to improve performance (but still warned against in the docs). Those performance issues are no longer a problem, and it is now possible to have deprecation warnings in the code to aid in transitioning away from such usage.

Activity

  1. added
    type-featureA feature request or enhancement
    stdlibStandard Library Python modules in the Lib/ directory
    3.12only security fixes
    on Jul 21, 2022
  2. brandtbucher commented on Jul 21, 2022

    @brandtbucher
    Member

    Those performance issues are no longer a problem

    As somebody who hasn't been following enum changes very closely: why is this?

  3. ethanfurman commented on Jul 21, 2022

    @ethanfurman
    MemberAuthor

    Performance timings on my system:

    The code
    import time
    import enum
    
    class Color(enum.Enum):
        RED = "Red"
        BLUE = "Blue"
        GREEN = "Green"
    RED, BLUE, GREEN = Color
    
    class FastColor:
        RED = Color.RED
        BLUE = Color.BLUE
        GREEN = Color.GREEN
    
    def f():
        for _ in range(10000000):
            Color.RED
            Color.BLUE
            Color.GREEN
    
    def g():
        for _ in range(10000000):
            FastColor.RED
            FastColor.BLUE
            FastColor.GREEN
    
    def h():
        for _ in range(10000000):
            RED
            BLUE
            GREEN
    
    import timeit
    print(round(timeit.timeit('f()', number=1, globals=globals()), 2), end='  ')
    print(round(timeit.timeit('g()', number=1, globals=globals()), 2), end='  ')
    print(round(timeit.timeit('h()', number=1, globals=globals()), 2), end=' \n\n')
    version enum "fast" enum global enum
    3.9 2.23 0.78 0.41
    3.10 2.68 0.91 0.47
    3.11 2.29 0.72 0.21
    3.12 2.21 0.62 0.14

    The 3.12 timings are with every enum member being accessed via the enum.property descriptor (i.e. no enum members being stored directly in the enum class __dict__).

    Out of curiosity I ran the above code with member.member access, both with and without the deprecation warning:

    warning no warning
    20.41 4.16

    So updating code to be correct will keep performance to 3.11 levels (or better).

  4. JelleZijlstra commented on Jul 21, 2022

    @JelleZijlstra
    Member

    How are the timings for accessing Color.RED.value affected?

  5. ethanfurman commented on Jul 21, 2022

    @ethanfurman
    MemberAuthor

    Those performance issues are no longer a problem

    As somebody who hasn't been following enum changes very closely: why is this?

    I can only imagine it's due to the work you and others have done. I had already noticed this in the other issue when comparing 3.10/3.11/3.12, and I was able to get another slight boost by storing the member directly in the descriptor and avoiding a dict lookup.

  6. ethanfurman commented on Jul 21, 2022

    @ethanfurman
    MemberAuthor

    How are the timings for accessing Color.RED.value affected?

    Some improvement, but I don't think I can take any credit for that (and those timings are not affected by this issue).

    version enum property simple python descriptor standard property
    3.9 5.96 4.9 2.11
    3.10 5.64 5.01 2.18
    3.11 3.67 3.46 1.58
    3.12 3.03 2.75 0.78
  7. ethanfurman commented on Jul 21, 2022

    @ethanfurman
    MemberAuthor

    I can make .name and .value normal properties (when no member by the same name exists), but when I tried that they stopped being reported by inspect and so also stopped showing up in pydoc.

  8. added a commit that references this issue on Jul 25, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    3.12only security fixesstdlibStandard Library Python modules in the Lib/ directorytype-featureA feature request or enhancement

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions