summaryrefslogtreecommitdiffstats
path: root/Lib/typing.py
diff options
context:
space:
mode:
authorAlex Waygood <Alex.Waygood@Gmail.com>2023-12-04 15:41:41 (GMT)
committerGitHub <noreply@github.com>2023-12-04 15:41:41 (GMT)
commitc718ab92a584fa658b6a626a744f5a71a048b47c (patch)
tree15a1a786040fe90f2e93d765be483955a7901d15 /Lib/typing.py
parent9560e0d6d7a316341939b4016e47e03bd5bf17c3 (diff)
downloadcpython-c718ab92a584fa658b6a626a744f5a71a048b47c.zip
cpython-c718ab92a584fa658b6a626a744f5a71a048b47c.tar.gz
cpython-c718ab92a584fa658b6a626a744f5a71a048b47c.tar.bz2
gh-74690: Optimise `isinstance()` and `issubclass()` calls against runtime-checkable protocols by avoiding costly `super()` calls (#112708)
Diffstat (limited to 'Lib/typing.py')
-rw-r--r--Lib/typing.py14
1 files changed, 11 insertions, 3 deletions
diff --git a/Lib/typing.py b/Lib/typing.py
index 4c19aad..aa64ed9 100644
--- a/Lib/typing.py
+++ b/Lib/typing.py
@@ -1782,6 +1782,14 @@ copyreg.pickle(ParamSpecKwargs, _pickle_pskwargs)
del _pickle_psargs, _pickle_pskwargs
+# Preload these once, as globals, as a micro-optimisation.
+# This makes a significant difference to the time it takes
+# to do `isinstance()`/`issubclass()` checks
+# against runtime-checkable protocols with only one callable member.
+_abc_instancecheck = ABCMeta.__instancecheck__
+_abc_subclasscheck = ABCMeta.__subclasscheck__
+
+
class _ProtocolMeta(ABCMeta):
# This metaclass is somewhat unfortunate,
# but is necessary for several reasons...
@@ -1841,7 +1849,7 @@ class _ProtocolMeta(ABCMeta):
"Instance and class checks can only be used with "
"@runtime_checkable protocols"
)
- return super().__subclasscheck__(other)
+ return _abc_subclasscheck(cls, other)
def __instancecheck__(cls, instance):
# We need this method for situations where attributes are
@@ -1850,7 +1858,7 @@ class _ProtocolMeta(ABCMeta):
return type.__instancecheck__(cls, instance)
if not getattr(cls, "_is_protocol", False):
# i.e., it's a concrete subclass of a protocol
- return super().__instancecheck__(instance)
+ return _abc_instancecheck(cls, instance)
if (
not getattr(cls, '_is_runtime_protocol', False) and
@@ -1859,7 +1867,7 @@ class _ProtocolMeta(ABCMeta):
raise TypeError("Instance and class checks can only be used with"
" @runtime_checkable protocols")
- if super().__instancecheck__(instance):
+ if _abc_instancecheck(cls, instance):
return True
getattr_static = _lazy_load_getattr_static()