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-134953: Make the True/False/None check more efficient by ambv · Pull Request #138931 · python/cpython Conversation
|
| ZERO_WIDTH_BRACKET = re.compile(r"\x01.*?\x02") | ||
| ZERO_WIDTH_TRANS = str.maketrans({"\x01": "", "\x02": ""}) | ||
| IDENTIFIERS_AFTER = {"def", "class"} | ||
| KEYWORD_CONSTANTS = {"True", "False", "None"} |
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
| KEYWORD_CONSTANTS = {"True", "False", "None"} | |
| KEYWORD_CONSTANTS = frozenset({"True", "False", "None"}) |
Is even faster.
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.
The compiler already does this automatically:
>>> def foo():
... KEYWORD_CONSTANTS = {"True", "False", "None"}
...
>>> foo.__code__.co_consts
(None, frozenset({'False', 'True', 'None'}))
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.
The compiler only does that for function locals, right? A module variable could be mutated from other modules.
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.
@auscompgeek You are right, for module level variables the optimization is not performed, so KEYWORD_CONSTANTS stays a set. For the free-threading build the performance difference is measurable:
Python 3.15.0a0 free-threading build (heads/main-dirty:2a54acf3c3d, Sep 1 2025, 14:33:50) [MSC v.1939 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import timeit
>>> timeit.timeit('[10 in s for ii in range(100)]', setup='from _pyrepl.utils import KEYWORD_CONSTANTS as s; f = frozenset(s)')
8.864965499844402
>>> timeit.timeit('[10 in f for ii in range(100)]', setup='from _pyrepl.utils import KEYWORD_CONSTANTS as s; f = frozenset(s)')
8.371516299899668
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.
@eendebakpt I'll accept a PR to wrap all global sets in _pyrepl.utils as frozensets. There's quite a few of them.
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.
I created a bit more general issue: #139003. For _pyrepl I'll make a PR.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
Thanks @ambv for the PR 🌮🎉.. I'm working now to backport this PR to: 3.14. |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
…nGH-138931) (cherry picked from commit 811acc8) Co-authored-by: Łukasz Langa <[email protected]>
|
GH-138939 is a backport of this pull request to the 3.14 branch. |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
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.