PEP 558: Update for conversation with Guido

- new open questions around how storage and updates
  will work
- note that we definitely *don't* want to return the
  write-through proxy from locals() at function scope
This commit is contained in:
Nick Coghlan 2017-09-08 16:14:04 -07:00
parent a6d74b181c
commit 94e6606edb
1 changed files with 63 additions and 0 deletions

View File

@ -125,6 +125,55 @@ function locals).
Open Questions
==============
Allowing local variable binding mutation outside trace functions
----------------------------------------------------------------
This PEP allows local variable bindings to be mutated whenever code has access
to the frame object - it doesn't restrict that ability to trace functions the
way the status quo does.
It does this since it wants to allow trace functions to make changes, while
removing the current bulk copy from ``f_locals`` back to the frame state when
the trace function returns.
An alternative approach might be to *temporarily* replace ``f_locals`` with
a write-through proxy while the trace function is running, and then swap it
back to the result of ``locals()`` when the trace function returns.
Where is the new ``locals()`` result stored?
--------------------------------------------
If ``locals()`` is a new mapping distinct from the write-through proxy stored in
``frame.f_locals``, where will that mapping be stored?
A new lazily initialised frame attribute seems like a plausible answer, but that
raises new questions around how that attribute will be managed for module and
class scopes (set to the same thing as ``f_locals``? Set to ``NULL``/``None``?)
Alternatively, it could be stored in ``f_locals`` most of the time (as it is
today), and have the write-through proxy stored in a separate lazily
initialised attribute that gets swapped in as ``f_locals`` only when calling
trace functions.
What happens with the default args for ``eval()`` and ``exec()``?
-----------------------------------------------------------------
These are formally defined as inheriting ``globals()`` and ``locals()`` from
the calling scope by default.
There doesn't seem to be any reason for the PEP to change this.
Does mutating the ``f_locals`` proxy refresh the ``locals()`` mapping?
----------------------------------------------------------------------
This is probably needed in order to retain the current behaviour where writes
to ``frame.f_locals`` are immediately visible via references obtained via
``locals()``.
How much compatibility is enough compatibility?
-----------------------------------------------
@ -227,6 +276,20 @@ This proposal deliberately *doesn't* formalise these semantics as is, since they
only make sense in terms of the historical evolution of the language and the
reference implementation, rather than being deliberately designed.
Rejected Alternatives
=====================
Making ``locals()`` return the write-through proxy directly
-----------------------------------------------------------
A number of changes have been made to ``locals()`` over the years to
deliberately make it *harder* for arbitrary code to mutate function local
variables without those changes being visible to the compiler at compile time.
As such the desired default semantics for ``locals()`` are those currently
seen when a tracing function *isn't* installed, rather than the mutating
behaviour currently seen when a tracing hook is installed.
Implementation
==============