]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-74690: Optimise `isinstance()` and `issubclass()` calls against runtime-checkable...
authorAlex Waygood <Alex.Waygood@Gmail.com>
Mon, 4 Dec 2023 15:41:41 +0000 (15:41 +0000)
committerGitHub <noreply@github.com>
Mon, 4 Dec 2023 15:41:41 +0000 (15:41 +0000)
Lib/typing.py
Misc/NEWS.d/next/Library/2023-12-04-14-05-24.gh-issue-74690.eODKRm.rst [new file with mode: 0644]

index 4c19aadabe3b87f7665c7881fa1ff7fcde6d9e07..aa64ed93f76fbfd871ac563f544c3466a4a87fce 100644 (file)
@@ -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()
diff --git a/Misc/NEWS.d/next/Library/2023-12-04-14-05-24.gh-issue-74690.eODKRm.rst b/Misc/NEWS.d/next/Library/2023-12-04-14-05-24.gh-issue-74690.eODKRm.rst
new file mode 100644 (file)
index 0000000..36d793f
--- /dev/null
@@ -0,0 +1,5 @@
+Speedup :func:`isinstance` checks by roughly 20% for
+:func:`runtime-checkable protocols <typing.runtime_checkable>`
+that only have one callable member.
+Speedup :func:`issubclass` checks for these protocols by roughly 10%.
+Patch by Alex Waygood.