bpo-45417: [Enum] fix quadratic behavior during creation (GH-28907) · python/cpython@b2af211

Original file line numberDiff line numberDiff line change

@@ -235,11 +235,18 @@ def __set_name__(self, enum_class, member_name):

235235

enum_member._sort_order_ = len(enum_class._member_names_)

236236

# If another member with the same value was already defined, the

237237

# new member becomes an alias to the existing one.

238-

for name, canonical_member in enum_class._member_map_.items():

239-

if canonical_member._value_ == enum_member._value_:

240-

enum_member = canonical_member

241-

break

242-

else:

238+

try:

239+

try:

240+

# try to do a fast lookup to avoid the quadratic loop

241+

enum_member = enum_class._value2member_map_[value]

242+

except TypeError:

243+

for name, canonical_member in enum_class._member_map_.items():

244+

if canonical_member._value_ == value:

245+

enum_member = canonical_member

246+

break

247+

else:

248+

raise KeyError

249+

except KeyError:

243250

# this could still be an alias if the value is multi-bit and the

244251

# class is a flag class

245252

if (

@@ -301,7 +308,7 @@ class _EnumDict(dict):

301308

"""

302309

def __init__(self):

303310

super().__init__()

304-

self._member_names = []

311+

self._member_names = {} # use a dict to keep insertion order

305312

self._last_values = []

306313

self._ignore = []

307314

self._auto_called = False

@@ -365,7 +372,7 @@ def __setitem__(self, key, value):

365372

)

366373

self._auto_called = True

367374

value = value.value

368-

self._member_names.append(key)

375+

self._member_names[key] = None

369376

self._last_values.append(value)

370377

super().__setitem__(key, value)

371378