PEP 558: Defined semantics for locals() (December 2019 edition)

Hi folks, I've finally updated PEP 558 and it's reference implementation based on Nathaniel's feedback back in May. The latest version of the PEP can now be found at https://www.python.org/dev/peps/pep-0558/, and I've created a discussion thread on Discourse: https://discuss.python.org/t/pep-558-defined-semantics-for-locals/2936 The latest version implements Nathaniel's "independent snapshot" proposal, and I like how that has turned out. The one thing that changed from the May discussion thread is that the refcount semantics of PyEval_GetLocals() (it returns a borrowed reference) meant that it had to keep the old behaviour of returning a reference to the internal dynamically updated shared "snapshot" at function scope, with a new API, PyEval_GetPyLocals(), providing the C equivalent of the locals() builtin. Cheers, Nick. -- Nick Coghlan | ncoghlan@gmail.com | Brisbane, Australia

Thanks for writing this up, Nick! My main question is about the remaining difference between semantics at the class/module versus function level: is it worth the additional cognitive complexity to have the class/module behavior be different from the function behavior? The "mutable" class/module behavior is really nice for debuggers, of course, but when you want that you really want it at *all* scopes, so having it available only some of the time feels like an unpredictable tool. I could imagine having a mode where everything (including function scopes) is required to permit mutability, but that would (a) be a lot of work (as you pointed out in the design discussion) and (b) would cause "debug mode" binaries to have to work so differently from "opt mode" ones that debugging would get harder for other reasons. I'm not sure that it *isn't* worth it to have this extra flexibility at the higher scope levels, but it isn't obvious to me that it is, and if that could lead to some code simplification, I wouldn't be sad! Yonatan On Mon, Dec 30, 2019 at 10:47 PM Nick Coghlan <ncoghlan@gmail.com> wrote:
Hi folks,
I've finally updated PEP 558 and it's reference implementation based on Nathaniel's feedback back in May.
The latest version of the PEP can now be found at https://www.python.org/dev/peps/pep-0558/, and I've created a discussion thread on Discourse: https://discuss.python.org/t/pep-558-defined-semantics-for-locals/2936
The latest version implements Nathaniel's "independent snapshot" proposal, and I like how that has turned out. The one thing that changed from the May discussion thread is that the refcount semantics of PyEval_GetLocals() (it returns a borrowed reference) meant that it had to keep the old behaviour of returning a reference to the internal dynamically updated shared "snapshot" at function scope, with a new API, PyEval_GetPyLocals(), providing the C equivalent of the locals() builtin.
Cheers, Nick.
-- Nick Coghlan | ncoghlan@gmail.com | Brisbane, Australia _______________________________________________ Python-Dev mailing list -- python-dev@python.org To unsubscribe send an email to python-dev-leave@python.org https://mail.python.org/mailman3/lists/python-dev.python.org/ Message archived at https://mail.python.org/archives/list/python-dev@python.org/message/GHN2GYJQ... Code of Conduct: http://python.org/psf/codeofconduct/

On Wed, 1 Jan 2020 at 10:42, Yonatan Zunger <zunger@humu.com> wrote:
Thanks for writing this up, Nick!
My main question is about the remaining difference between semantics at the class/module versus function level: is it worth the additional cognitive complexity to have the class/module behavior be different from the function behavior?
Mutating values through locals() has long worked at class and module scope, and folks rely on that often enough that we don't want to break their code. Correctly supporting mutation via locals() also falls naturally out of the runtime semantics of those scopes (at module scope, locals() returns the same namespace as globals() does, while at class scope it returns the same namespace as will eventually be passed to the metaclass to create the new class object). By contrast, mutation via locals() at function scope hasn't worked consistently since fast locals were introduced, and that predates even statically nested scopes (I went trawling through the repo history to try to work out when they were first added, and made it as far as "some time before 1997, since [1] changed how they worked to make them faster, but was replacing an even older list-based mechanism"). Cheers, Nick. [1] https://github.com/python/cpython/commit/f3e85a0356e679ed9ff8d13236ff8e9f77a... -- Nick Coghlan | ncoghlan@gmail.com | Brisbane, Australia

Makes sense. Thanks for the clarification! On Wed, Jan 1, 2020 at 1:30 AM Nick Coghlan <ncoghlan@gmail.com> wrote:
On Wed, 1 Jan 2020 at 10:42, Yonatan Zunger <zunger@humu.com> wrote:
Thanks for writing this up, Nick!
My main question is about the remaining difference between semantics at
the class/module versus function level: is it worth the additional cognitive complexity to have the class/module behavior be different from the function behavior?
Mutating values through locals() has long worked at class and module scope, and folks rely on that often enough that we don't want to break their code. Correctly supporting mutation via locals() also falls naturally out of the runtime semantics of those scopes (at module scope, locals() returns the same namespace as globals() does, while at class scope it returns the same namespace as will eventually be passed to the metaclass to create the new class object).
By contrast, mutation via locals() at function scope hasn't worked consistently since fast locals were introduced, and that predates even statically nested scopes (I went trawling through the repo history to try to work out when they were first added, and made it as far as "some time before 1997, since [1] changed how they worked to make them faster, but was replacing an even older list-based mechanism").
Cheers, Nick.
[1] https://github.com/python/cpython/commit/f3e85a0356e679ed9ff8d13236ff8e9f77a...
-- Nick Coghlan | ncoghlan@gmail.com | Brisbane, Australia
participants (2)
-
Nick Coghlan
-
Yonatan Zunger