.. c:function:: PyObject* PyFrame_GetLocals(PyFrameObject *frame)
Get the *frame*'s :attr:`~frame.f_locals` attribute.
- If the frame refers to a function or comprehension, this returns
- a write-through proxy object that allows modifying the locals.
- In all other cases (classes, modules) it returns the :class:`dict`
- representing the frame locals directly.
+ If the frame refers to an :term:`optimized scope`, this returns a
+ write-through proxy object that allows modifying the locals.
+ In all other cases (classes, modules, :func:`exec`, :func:`eval`) it returns
+ the mapping representing the frame locals directly (as described for
+ :func:`locals`).
Return a :term:`strong reference`.
.. versionadded:: 3.11
.. versionchanged:: 3.13
- Return a proxy object for functions and comprehensions.
+ As part of :pep:`667`, return a proxy object for optimized scopes.
.. c:function:: int PyFrame_GetLineNumber(PyFrameObject *frame)
(methods). Also the ultimate base class of any :term:`new-style
class`.
+ optimized scope
+ A scope where target local variable names are reliably known to the
+ compiler when the code is compiled, allowing optimization of read and
+ write access to these names. The local namespaces for functions,
+ generators, coroutines, comprehensions, and generator expressions are
+ optimized in this fashion. Note: most interpreter optimizations are
+ applied to all scopes, only those relying on a known set of local
+ and nonlocal variable names are restricted to optimized scopes.
+
package
A Python :term:`module` which can contain submodules or recursively,
subpackages. Technically, a package is a Python module with a
This class deals with parsing and interpreter state (the user's namespace); it
does not deal with input buffering or prompting or input file naming (the
filename is always passed in explicitly). The optional *locals* argument
- specifies the dictionary in which code will be executed; it defaults to a newly
- created dictionary with key ``'__name__'`` set to ``'__console__'`` and key
- ``'__doc__'`` set to ``None``.
+ specifies a mapping to use as the namespace in which code will be executed;
+ it defaults to a newly created dictionary with key ``'__name__'`` set to
+ ``'__console__'`` and key ``'__doc__'`` set to ``None``.
.. class:: InteractiveConsole(locals=None, filename="<console>", local_exit=False)
The *expression* argument is parsed and evaluated as a Python expression
(technically speaking, a condition list) using the *globals* and *locals*
- dictionaries as global and local namespace. If the *globals* dictionary is
+ mappings as global and local namespace. If the *globals* dictionary is
present and does not contain a value for the key ``__builtins__``, a
reference to the dictionary of the built-in module :mod:`builtins` is
inserted under that key before *expression* is parsed. That way you can
control what builtins are available to the executed code by inserting your
own ``__builtins__`` dictionary into *globals* before passing it to
- :func:`eval`. If the *locals* dictionary is omitted it defaults to the
- *globals* dictionary. If both dictionaries are omitted, the expression is
+ :func:`eval`. If the *locals* mapping is omitted it defaults to the
+ *globals* dictionary. If both mappings are omitted, the expression is
executed with the *globals* and *locals* in the environment where
- :func:`eval` is called. Note, *eval()* does not have access to the
+ :func:`eval` is called. Note, *eval()* will only have access to the
:term:`nested scopes <nested scope>` (non-locals) in the enclosing
- environment.
+ environment if they are already referenced in the scope that is calling
+ :func:`eval` (e.g. via a :keyword:`nonlocal` statement).
Example:
The *globals* and *locals* arguments can now be passed as keywords.
+ .. versionchanged:: 3.13
+
+ The semantics of the default *locals* namespace have been adjusted as
+ described for the :func:`locals` builtin.
+
.. index:: pair: built-in function; exec
.. function:: exec(source, /, globals=None, locals=None, *, closure=None)
.. note::
- Most users should just pass a *globals* argument and never *locals*.
- If exec gets two separate objects as *globals* and *locals*, the code
- will be executed as if it were embedded in a class definition.
+ When ``exec`` gets two separate objects as *globals* and *locals*, the
+ code will be executed as if it were embedded in a class definition. This
+ means functions and classes defined in the executed code will not be able
+ to access variables assigned at the top level (as the "top level"
+ variables are treated as class variables in a class definition).
+ Passing a :class:`collections.ChainMap` instance as *globals* allows name
+ lookups to be chained across multiple mappings without triggering this
+ behaviour. Values assigned to top level names in the executed code can be
+ retrieved by passing an empty dictionary as the first entry in the chain.
If the *globals* dictionary does not contain a value for the key
``__builtins__``, a reference to the dictionary of the built-in module
.. note::
The built-in functions :func:`globals` and :func:`locals` return the current
- global and local dictionary, respectively, which may be useful to pass around
+ global and local namespace, respectively, which may be useful to pass around
for use as the second and third argument to :func:`exec`.
.. note::
The *globals* and *locals* arguments can now be passed as keywords.
+ .. versionchanged:: 3.13
+
+ The semantics of the default *locals* namespace have been adjusted as
+ described for the :func:`locals` builtin.
+
.. function:: filter(function, iterable)
variable names as the keys, and their currently bound references as the
values.
- At module scope, as well as when using ``exec()`` or ``eval()`` with a
- single namespace, this function returns the same namespace as ``globals()``.
+ At module scope, as well as when using :func:`exec` or :func:`eval` with
+ a single namespace, this function returns the same namespace as
+ :func:`globals`.
At class scope, it returns the namespace that will be passed to the
metaclass constructor.
When using ``exec()`` or ``eval()`` with separate local and global
- namespaces, it returns the local namespace passed in to the function call.
+ arguments, it returns the local namespace passed in to the function call.
In all of the above cases, each call to ``locals()`` in a given frame of
execution will return the *same* mapping object. Changes made through
- the mapping object returned from ``locals()`` will be visible as bound,
- rebound, or deleted local variables, and binding, rebinding, or deleting
- local variables will immediately affect the contents of the returned mapping
- object.
-
- At function scope (including for generators and coroutines), each call to
- ``locals()`` instead returns a fresh dictionary containing the current
- bindings of the function's local variables and any nonlocal cell references.
- In this case, name binding changes made via the returned dict are *not*
- written back to the corresponding local variables or nonlocal cell
- references, and binding, rebinding, or deleting local variables and nonlocal
- cell references does *not* affect the contents of previously returned
- dictionaries.
+ the mapping object returned from ``locals()`` will be visible as assigned,
+ reassigned, or deleted local variables, and assigning, reassigning, or
+ deleting local variables will immediately affect the contents of the
+ returned mapping object.
+
+ In an :term:`optimized scope` (including functions, generators, and
+ coroutines), each call to ``locals()`` instead returns a fresh dictionary
+ containing the current bindings of the function's local variables and any
+ nonlocal cell references. In this case, name binding changes made via the
+ returned dict are *not* written back to the corresponding local variables
+ or nonlocal cell references, and assigning, reassigning, or deleting local
+ variables and nonlocal cell references does *not* affect the contents
+ of previously returned dictionaries.
+
+ Calling ``locals()`` as part of a comprehension in a function, generator, or
+ coroutine is equivalent to calling it in the containing scope, except that
+ the comprehension's initialised iteration variables will be included. In
+ other scopes, it behaves as if the comprehension were running as a nested
+ function.
+
+ Calling ``locals()`` as part of a generator expression is equivalent to
+ calling it in a nested generator function.
+
+ .. versionchanged:: 3.12
+ The behaviour of ``locals()`` in a comprehension has been updated as
+ described in :pep:`709`.
.. versionchanged:: 3.13
- In previous versions, the semantics of mutating the mapping object
- returned from this function were formally undefined. In CPython
- specifically, the mapping returned at function scope could be
- implicitly refreshed by other operations, such as calling ``locals()``
- again. Obtaining the legacy CPython behaviour now requires explicit
- calls to update the initially returned dictionary with the results
- of subsequent calls to ``locals()``.
+ As part of :pep:`667`, the semantics of mutating the mapping objects
+ returned from this function are now defined. The behavior in
+ :term:`optimized scopes <optimized scope>` is now as described above.
+ Aside from being defined, the behaviour in other scopes remains
+ unchanged from previous versions.
.. function:: map(function, iterable, *iterables)
:attr:`~object.__dict__` attributes (for example, classes use a
:class:`types.MappingProxyType` to prevent direct dictionary updates).
- Without an argument, :func:`vars` acts like :func:`locals`. Note, the
- locals dictionary is only useful for reads since updates to the locals
- dictionary are ignored.
+ Without an argument, :func:`vars` acts like :func:`locals`.
A :exc:`TypeError` exception is raised if an object is specified but
it doesn't have a :attr:`~object.__dict__` attribute (for example, if
its class defines the :attr:`~object.__slots__` attribute).
+ .. versionchanged:: 3.13
+
+ The result of calling this function without an argument has been
+ updated as described for the :func:`locals` builtin.
+
+
.. function:: zip(*iterables, strict=False)
Iterate over several iterables in parallel, producing tuples with an item
0
(Pdb)
+.. versionchanged:: 3.13
+ The implementation of :pep:`667` means that name assignments made via ``pdb``
+ will immediately affect the active scope, even when running inside an
+ :term:`optimized scope`.
+
The module defines the following functions; each enters the debugger in a
slightly different way:
.. pdbcommand:: interact
- Start an interactive interpreter (using the :mod:`code` module) whose global
- namespace contains all the (global and local) names found in the current
- scope. Use ``exit()`` or ``quit()`` to exit the interpreter and return to
- the debugger.
+ Start an interactive interpreter (using the :mod:`code` module) in a new
+ global namespace initialised from the local and global namespaces for the
+ current scope. Use ``exit()`` or ``quit()`` to exit the interpreter and
+ return to the debugger.
.. note::
- Because interact creates a new global namespace with the current global
- and local namespace for execution, assignment to variables will not
- affect the original namespaces.
- However, modification to the mutable objects will be reflected in the
- original namespaces.
+ As ``interact`` creates a new dedicated namespace for code execution,
+ assignments to variables will not affect the original namespaces.
+ However, modifications to any referenced mutable objects will be reflected
+ in the original namespaces as usual.
.. versionadded:: 3.2
.. function:: runctx(command, globals, locals, filename=None, sort=-1)
This function is similar to :func:`run`, with added arguments to supply the
- globals and locals dictionaries for the *command* string. This routine
+ globals and locals mappings for the *command* string. This routine
executes::
exec(command, globals, locals)
attribute accessed (which also happens when casting it to a :class:`tuple`).
:attr:`~FrameSummary.line` may be directly provided, and will prevent line
lookups happening at all. *locals* is an optional local variable
- dictionary, and if supplied the variable representations are stored in the
+ mapping, and if supplied the variable representations are stored in the
summary for later display.
:class:`!FrameSummary` instances have the following attributes:
* - .. attribute:: frame.f_locals
- The dictionary used by the frame to look up
:ref:`local variables <naming>`.
- If the frame refers to a function or comprehension,
+ If the frame refers to an :term:`optimized scope`,
this may return a write-through proxy object.
.. versionchanged:: 3.13
Performance improvements are modest -- we expect to be improving this
over the next few releases.
-* :pep:`667`: :attr:`FrameType.f_locals <frame.f_locals>` when used in
- a function now returns a write-through proxy to the frame's locals,
- rather than a ``dict``. See the PEP for corresponding C API changes
- and deprecations.
+* :pep:`667`: The :func:`locals` builtin now has
+ :ref:`defined semantics <whatsnew313-locals-semantics>` when mutating the
+ returned mapping. Python debuggers and similar tools may now more reliably
+ update local variables in optimized frames even during concurrent code
+ execution.
New typing features:
through ``self.X`` from any function in its body. (Contributed by Irit Katriel
in :gh:`115775`.)
+.. _whatsnew313-locals-semantics:
+
+Defined mutation semantics for ``locals()``
+-------------------------------------------
+
+Historically, the expected result of mutating the return value of :func:`locals`
+has been left to individual Python implementations to define.
+
+Through :pep:`667`, Python 3.13 standardises the historical behaviour of CPython
+for most code execution scopes, but changes
+:term:`optimized scopes <optimized scope>` (functions, generators, coroutines,
+comprehensions, and generator expressions) to explicitly return independent
+snapshots of the currently assigned local variables, including locally
+referenced nonlocal variables captured in closures.
+
+To ensure debuggers and similar tools can reliably update local variables in
+scopes affected by this change, :attr:`FrameType.f_locals <frame.f_locals>` now
+returns a write-through proxy to the frame's local and locally referenced
+nonlocal variables in these scopes, rather than returning an inconsistently
+updated shared ``dict`` instance with undefined runtime semantics.
+
+See :pep:`667` for more details, including related C API changes and
+deprecations.
+
+(PEP and implementation contributed by Mark Shannon and Tian Gao in
+:gh:`74929`. Documentation updates provided by Guido van Rossum and
+Alyssa Coghlan.)
+
Incremental Garbage Collection
------------------------------
returned by :meth:`zipfile.ZipFile.open` was changed from ``'r'`` to ``'rb'``.
(Contributed by Serhiy Storchaka in :gh:`115961`.)
+* Calling :func:`locals` in an :term:`optimized scope` now produces an
+ independent snapshot on each call, and hence no longer implicitly updates
+ previously returned references. Obtaining the legacy CPython behaviour now
+ requires explicit calls to update the initially returned dictionary with the
+ results of subsequent calls to ``locals()``. (Changed as part of :pep:`667`.)
+
+* Calling :func:`locals` from a comprehension at module or class scope
+ (including via ``exec`` or ``eval``) once more behaves as if the comprehension
+ were running as an independent nested function (i.e. the local variables from
+ the containing scope are not included). In Python 3.12, this had changed
+ to include the local variables from the containing scope when implementing
+ :pep:`709`. (Changed as part of :pep:`667`.)
+
+* Accessing :attr:`FrameType.f_locals <frame.f_locals>` in an
+ :term:`optimized scope` now returns a write-through proxy rather than a
+ snapshot that gets updated at ill-specified times. If a snapshot is desired,
+ it must be created explicitly with ``dict`` or the proxy's ``.copy()`` method.
+ (Changed as part of :pep:`667`.)
Changes in the C API
--------------------
def __init__(self, locals=None):
"""Constructor.
- The optional 'locals' argument specifies the dictionary in
- which code will be executed; it defaults to a newly created
- dictionary with key "__name__" set to "__console__" and key
- "__doc__" set to None.
+ The optional 'locals' argument specifies a mapping to use as the
+ namespace in which code will be executed; it defaults to a newly
+ created dictionary with key "__name__" set to "__console__" and
+ key "__doc__" set to None.
"""
if locals is None:
self.tb_lineno[tb.tb_frame] = lineno
tb = tb.tb_next
self.curframe = self.stack[self.curindex][0]
- # The f_locals dictionary is updated from the actual frame
- # locals whenever the .f_locals accessor is called, so we
- # cache it here to ensure that modifications are not overwritten.
+ # The f_locals dictionary used to be updated from the actual frame
+ # locals whenever the .f_locals accessor was called, so it was
+ # cached here to ensure that modifications were not overwritten. While
+ # the caching is no longer required now that f_locals is a direct proxy
+ # on optimized frames, it's also harmless, so the code structure has
+ # been left unchanged.
self.curframe_locals = self.curframe.f_locals
self.set_convenience_variable(self.curframe, '_frame', self.curframe)