]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-149436: Speed up inspect.getattr_static for the common-metaclass case (#149437)
authorPieter Eendebak <pieter.eendebak@gmail.com>
Sun, 10 May 2026 02:52:52 +0000 (04:52 +0200)
committerGitHub <noreply@github.com>
Sun, 10 May 2026 02:52:52 +0000 (19:52 -0700)
Consecutive MRO entries usually share their metaclass, so call
_shadowed_dict at most once per distinct metaclass.

Lib/inspect.py
Misc/NEWS.d/next/Library/2026-05-08-14-24-16.gh-issue-149436.dEV02X.rst [new file with mode: 0644]

index a96b3dc954ef0ca850b17ca158ea79255460cfc5..3e85625cd30263314d06f8667601c9165aeecf3c 100644 (file)
@@ -1709,9 +1709,13 @@ def _check_instance(obj, attr):
 
 
 def _check_class(klass, attr):
+    last_meta = None
     for entry in _static_getmro(klass):
-        if _shadowed_dict(type(entry)) is _sentinel and attr in entry.__dict__:
-            return entry.__dict__[attr]
+        meta = type(entry)
+        if meta is last_meta or _shadowed_dict(meta) is _sentinel:
+            last_meta = meta
+            if attr in entry.__dict__:
+                return entry.__dict__[attr]
     return _sentinel
 
 
@@ -1743,6 +1747,9 @@ def _shadowed_dict(klass):
     # destroyed, and the dynamically created classes happen to be the only
     # objects that hold strong references to other objects that take up a
     # significant amount of memory.
+    # Fast path: `type` is the dominant caller; result is always _sentinel.
+    if klass is type:
+        return _sentinel
     return _shadowed_dict_from_weakref_mro_tuple(
         *[make_weakref(entry) for entry in _static_getmro(klass)]
     )
diff --git a/Misc/NEWS.d/next/Library/2026-05-08-14-24-16.gh-issue-149436.dEV02X.rst b/Misc/NEWS.d/next/Library/2026-05-08-14-24-16.gh-issue-149436.dEV02X.rst
new file mode 100644 (file)
index 0000000..401cf04
--- /dev/null
@@ -0,0 +1 @@
+Improve performance of :meth:`inspect.getattr_static`.