diff options
author | Alex Waygood <Alex.Waygood@Gmail.com> | 2023-03-31 20:54:50 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-03-31 20:54:50 (GMT) |
commit | 361a3eaf1b6bf3360e34388cc909307ddd20737b (patch) | |
tree | 8ee2dad5f6082ff0a2ccec5e0a324af7826c443a /Lib | |
parent | 2a4d8c0a9e88f45047da640ce5a92b304d2d39b1 (diff) | |
download | cpython-361a3eaf1b6bf3360e34388cc909307ddd20737b.zip cpython-361a3eaf1b6bf3360e34388cc909307ddd20737b.tar.gz cpython-361a3eaf1b6bf3360e34388cc909307ddd20737b.tar.bz2 |
gh-74690: Micro-optimise `typing._get_protocol_attrs` (#103152)
Improve performance of `isinstance()` checks against runtime-checkable protocols
Diffstat (limited to 'Lib')
-rw-r--r-- | Lib/typing.py | 20 |
1 files changed, 12 insertions, 8 deletions
diff --git a/Lib/typing.py b/Lib/typing.py index 3d086dc..a88542c 100644 --- a/Lib/typing.py +++ b/Lib/typing.py @@ -1903,15 +1903,19 @@ class _TypingEllipsis: """Internal placeholder for ... (ellipsis).""" -_TYPING_INTERNALS = ['__parameters__', '__orig_bases__', '__orig_class__', - '_is_protocol', '_is_runtime_protocol'] +_TYPING_INTERNALS = frozenset({ + '__parameters__', '__orig_bases__', '__orig_class__', + '_is_protocol', '_is_runtime_protocol' +}) -_SPECIAL_NAMES = ['__abstractmethods__', '__annotations__', '__dict__', '__doc__', - '__init__', '__module__', '__new__', '__slots__', - '__subclasshook__', '__weakref__', '__class_getitem__'] +_SPECIAL_NAMES = frozenset({ + '__abstractmethods__', '__annotations__', '__dict__', '__doc__', + '__init__', '__module__', '__new__', '__slots__', + '__subclasshook__', '__weakref__', '__class_getitem__' +}) # 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): @@ -1922,10 +1926,10 @@ def _get_protocol_attrs(cls): """ attrs = set() for base in cls.__mro__[:-1]: # without object - if base.__name__ in ('Protocol', 'Generic'): + if base.__name__ in {'Protocol', 'Generic'}: continue 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: attrs.add(attr) return attrs |