Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What about classes that define custom
__dir__()
methods? What about classes that define custom__getattribute__
methods? I think this approach is very riskyThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, is there any C-implemented alternative to
dir
, that returns some iterable of the attribute names? I sawinspect.getmembers_static
, but it is mostly plain python and way too slow. If custom__dir__
is a worry, one could maybe useobject.__dir__(instance)
.dir itself is even inefficient since it sorts the names, here we really only need something that iterates over the names.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In regard to the custom
__getattribute__
stuff, I think the current code already suffers from that, no? The docs say aboutgetattr_static
:There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not that I know of
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah indeed; good point
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So really the issue here seems that
getattr_static
is just really slow (I re-ran the test, replacing it with plaingetattr
and got 11x speedup)getattr
can be slow if it triggers some computation.isinstance(x, proto)
only checks statically known attributes and can give incorrect results if certain attributes are defined dynamically.__hasattr__
to communicate which attributes are set dynamically.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Your analysis is correct.
Note that we changed these two bullet points in Python 3.12 after long discussions in python/typing#1363 and #102433. Previously,
isinstance()
checks didn't useinspect.getattr_static
, and did resolve dynamically defined attributes. But it was decided that that behaviour was bad, so we decided to accept the performance penalty in order to have more correct and less unexpected behaviour. (And through various other performance optimisations to compensate for that,isinstance()
checks against runtime-checkable protocols are still overall much faster in Python 3.12 than in Python 3.11, despite the slowdown from switching toinspect.getattr_static
.)