GeezerVisonThe World Wide Web, restored to 800 pixels of glory. | ||||||||||||||||||||||||||||||||||||
| Home|About|Gaming cabinet|Archives|How it works|Starter sites | ||||||||||||||||||||||||||||||||||||
GeezerVison is showing github.com — gh-156413: Let a `None`-valued non-callable member keep the Protocol fast path by adamtheturtle · Pull Request #156451 · python/cpython Conversation
|
| N | Good |
Bad, before |
Bad, after |
|---|---|---|---|
| 2 | 178 | 1334 (7.5x) | 162 (1.0x) |
| 5 | 166 | 2861 (17x) | 170 (1.0x) |
| 20 | 167 | 10704 (64x) | 169 (1.0x) |
| 50 | 183 | 26882 (147x) | 172 (1.0x) |
| 110 | 192 | 55820 (291x) | 186 (1.0x) |
The before column scales at roughly 500 ns per protocol member. After the change Bad is a cache hit like Good, and Good itself is unaffected.
This gives _proto_hook the same rule, so such a class is cached like any other. None-valued method members are still rejected, and a missing attribute still fails.
The only externally visible change is via _allow_reckless_class_checks: an issubclass() originating in abc, functools or _py_abc now returns True where it returned False, which is what isinstance() already answers for the same pair. A direct issubclass() still raises TypeError for protocols with non-method members, so user-facing behaviour is unchanged.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
…col fast path `_ProtocolMeta.__instancecheck__` treats a member set to `None` as "explicitly not implemented" only for callable members, but `_proto_hook` treated any `None` in a class `__dict__` that way. A class that set a non-callable protocol member to `None` therefore passed `isinstance()` but was rejected by the subclass hook, so it never entered `ABCMeta`'s cache and re-walked every protocol member on every call. Give `_proto_hook` the same rule, so such a class is cached like any other. `None`-valued *method* members are still rejected. Co-Authored-By: Claude Opus 5 (1M context) <[email protected]> Claude-Session: https://claude.ai/code/session_016TM2nkuPFj6FFmZyUJZYUQ
| # all of the protocol members again. | ||
| @runtime_checkable | ||
| class P(Protocol): | ||
| x = 1 |
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
Can you check with a protocol defining a property as well? it's not really a callable strictly speaking.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
(Deleted comment that the bot wrote).
Yes - added in a new commit.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
A property is not callable when looked up on the class, so it lands in __non_callable_proto_members__ alongside a plain class attribute. Both subtests fail without the change. Co-Authored-By: Claude Opus 5 (1M context) <[email protected]> Claude-Session: https://claude.ai/code/session_016TM2nkuPFj6FFmZyUJZYUQ
There was an error while loading. Please reload this page.
Successfully merging this pull request may close these issues.
There was an error while loading. Please reload this page.