gh-74690: Micro-optimise typing._get_protocol_attrs (#103152)

Improve performance of `isinstance()` checks against runtime-checkable protocols
This commit is contained in:
Alex Waygood 2023-03-31 21:54:50 +01:00 committed by GitHub
parent 2a4d8c0a9e
commit 361a3eaf1b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -1903,15 +1903,19 @@ class _TypingEllipsis:
"""Internal placeholder for ... (ellipsis).""" """Internal placeholder for ... (ellipsis)."""
_TYPING_INTERNALS = ['__parameters__', '__orig_bases__', '__orig_class__', _TYPING_INTERNALS = frozenset({
'_is_protocol', '_is_runtime_protocol'] '__parameters__', '__orig_bases__', '__orig_class__',
'_is_protocol', '_is_runtime_protocol'
})
_SPECIAL_NAMES = ['__abstractmethods__', '__annotations__', '__dict__', '__doc__', _SPECIAL_NAMES = frozenset({
'__abstractmethods__', '__annotations__', '__dict__', '__doc__',
'__init__', '__module__', '__new__', '__slots__', '__init__', '__module__', '__new__', '__slots__',
'__subclasshook__', '__weakref__', '__class_getitem__'] '__subclasshook__', '__weakref__', '__class_getitem__'
})
# These special attributes will be not collected as protocol members. # These special attributes will be not collected as protocol members.
EXCLUDED_ATTRIBUTES = _TYPING_INTERNALS + _SPECIAL_NAMES + ['_MutableMapping__marker'] EXCLUDED_ATTRIBUTES = _TYPING_INTERNALS | _SPECIAL_NAMES | {'_MutableMapping__marker'}
def _get_protocol_attrs(cls): def _get_protocol_attrs(cls):
@ -1922,10 +1926,10 @@ def _get_protocol_attrs(cls):
""" """
attrs = set() attrs = set()
for base in cls.__mro__[:-1]: # without object for base in cls.__mro__[:-1]: # without object
if base.__name__ in ('Protocol', 'Generic'): if base.__name__ in {'Protocol', 'Generic'}:
continue continue
annotations = getattr(base, '__annotations__', {}) annotations = getattr(base, '__annotations__', {})
for attr in list(base.__dict__.keys()) + list(annotations.keys()): for attr in (*base.__dict__, *annotations):
if not attr.startswith('_abc_') and attr not in EXCLUDED_ATTRIBUTES: if not attr.startswith('_abc_') and attr not in EXCLUDED_ATTRIBUTES:
attrs.add(attr) attrs.add(attr)
return attrs return attrs