mirror of
https://github.com/python/cpython.git
synced 2025-08-04 08:59:19 +00:00
bpo-45417: [Enum] fix quadratic behavior during creation (GH-28907)
Creating an Enum exhibited quadratic behavior based on the number of members in three places: - `EnumDict._member_names`: a list searched with each new member's name - member creation: a `for` loop checking each existing member to see if new member was a duplicate - `auto()` values: a list of all previous values in enum was copied before being sent to `_generate_next_value()` Two of those issues have been resolved: - `_EnumDict._member_names` is now a dictionary so lookups are fast - member creation tries a fast value lookup before falling back to the slower `for` loop lookup The third issue still remains, as `_generate_next_value_()` can be user-overridden and could corrupt the last values list if it were not copied.
This commit is contained in:
parent
0bbea0723e
commit
b2af211e22
2 changed files with 16 additions and 7 deletions
21
Lib/enum.py
21
Lib/enum.py
|
@ -235,11 +235,18 @@ class _proto_member:
|
|||
enum_member._sort_order_ = len(enum_class._member_names_)
|
||||
# If another member with the same value was already defined, the
|
||||
# new member becomes an alias to the existing one.
|
||||
for name, canonical_member in enum_class._member_map_.items():
|
||||
if canonical_member._value_ == enum_member._value_:
|
||||
enum_member = canonical_member
|
||||
break
|
||||
else:
|
||||
try:
|
||||
try:
|
||||
# try to do a fast lookup to avoid the quadratic loop
|
||||
enum_member = enum_class._value2member_map_[value]
|
||||
except TypeError:
|
||||
for name, canonical_member in enum_class._member_map_.items():
|
||||
if canonical_member._value_ == value:
|
||||
enum_member = canonical_member
|
||||
break
|
||||
else:
|
||||
raise KeyError
|
||||
except KeyError:
|
||||
# this could still be an alias if the value is multi-bit and the
|
||||
# class is a flag class
|
||||
if (
|
||||
|
@ -301,7 +308,7 @@ class _EnumDict(dict):
|
|||
"""
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self._member_names = []
|
||||
self._member_names = {} # use a dict to keep insertion order
|
||||
self._last_values = []
|
||||
self._ignore = []
|
||||
self._auto_called = False
|
||||
|
@ -365,7 +372,7 @@ class _EnumDict(dict):
|
|||
)
|
||||
self._auto_called = True
|
||||
value = value.value
|
||||
self._member_names.append(key)
|
||||
self._member_names[key] = None
|
||||
self._last_values.append(value)
|
||||
super().__setitem__(key, value)
|
||||
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
Fix quadratic behaviour in the enum module: Creation of enum classes with a
|
||||
lot of entries was quadratic.
|
Loading…
Add table
Add a link
Reference in a new issue