Skip to content

Commit 0e0a2da

Browse files
miss-islingtonncoghlanwillingc
authored
[3.13] gh-70870: Clarify dual usage of 'free variable' (GH-122545) (#125088)
The term "free variable" has unfortunately become genuinely ambiguous over the years (presumably due to the names of some relevant code object instance attributes). While we can't eliminate that ambiguity at this late date, we can at least alert people to the potential ambiguity by describing both the formal meaning of the term and the common alternative use as a direct synonym for "closure variable". --------- (cherry picked from commit 2739099) Co-authored-by: Alyssa Coghlan <[email protected]> Co-authored-by: Carol Willing <[email protected]>
1 parent e28f2c6 commit 0e0a2da

File tree

9 files changed

+66
-21
lines changed

9 files changed

+66
-21
lines changed

Doc/c-api/code.rst

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,13 @@ bound into a function.
3232
3333
.. c:function:: Py_ssize_t PyCode_GetNumFree(PyCodeObject *co)
3434
35-
Return the number of free variables in a code object.
35+
Return the number of :term:`free (closure) variables <closure variable>`
36+
in a code object.
3637
3738
.. c:function:: int PyUnstable_Code_GetFirstFree(PyCodeObject *co)
3839
39-
Return the position of the first free variable in a code object.
40+
Return the position of the first :term:`free (closure) variable <closure variable>`
41+
in a code object.
4042
4143
.. versionchanged:: 3.13
4244
@@ -144,7 +146,8 @@ bound into a function.
144146
145147
Equivalent to the Python code ``getattr(co, 'co_freevars')``.
146148
Returns a new reference to a :c:type:`PyTupleObject` containing the names of
147-
the free variables. On error, ``NULL`` is returned and an exception is raised.
149+
the :term:`free (closure) variables <closure variable>`. On error, ``NULL`` is returned
150+
and an exception is raised.
148151
149152
.. versionadded:: 3.11
150153

Doc/glossary.rst

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,28 @@ Glossary
226226
A variable defined in a class and intended to be modified only at
227227
class level (i.e., not in an instance of the class).
228228

229+
closure variable
230+
A :term:`free variable` referenced from a :term:`nested scope` that is defined in an outer
231+
scope rather than being resolved at runtime from the globals or builtin namespaces.
232+
May be explicitly defined with the :keyword:`nonlocal` keyword to allow write access,
233+
or implicitly defined if the variable is only being read.
234+
235+
For example, in the ``inner`` function in the following code, both ``x`` and ``print`` are
236+
:term:`free variables <free variable>`, but only ``x`` is a *closure variable*::
237+
238+
def outer():
239+
x = 0
240+
def inner():
241+
nonlocal x
242+
x += 1
243+
print(x)
244+
return inner
245+
246+
Due to the :attr:`codeobject.co_freevars` attribute (which, despite its name, only
247+
includes the names of closure variables rather than listing all referenced free
248+
variables), the more general :term:`free variable` term is sometimes used even
249+
when the intended meaning is to refer specifically to closure variables.
250+
229251
complex number
230252
An extension of the familiar real number system in which all numbers are
231253
expressed as a sum of a real part and an imaginary part. Imaginary
@@ -444,6 +466,13 @@ Glossary
444466
the :term:`global interpreter lock` which allows only one thread to
445467
execute Python bytecode at a time. See :pep:`703`.
446468

469+
free variable
470+
Formally, as defined in the :ref:`language execution model <bind_names>`, a free
471+
variable is any variable used in a namespace which is not a local variable in that
472+
namespace. See :term:`closure variable` for an example.
473+
Pragmatically, due to the name of the :attr:`codeobject.co_freevars` attribute,
474+
the term is also sometimes used as a synonym for :term:`closure variable`.
475+
447476
function
448477
A series of statements which returns some value to a caller. It can also
449478
be passed zero or more :term:`arguments <argument>` which may be used in

Doc/library/dis.rst

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1431,7 +1431,7 @@ iterations of the loop.
14311431
slot ``i`` of the "fast locals" storage in this mapping.
14321432
If the name is not found there, loads it from the cell contained in
14331433
slot ``i``, similar to :opcode:`LOAD_DEREF`. This is used for loading
1434-
free variables in class bodies (which previously used
1434+
:term:`closure variables <closure variable>` in class bodies (which previously used
14351435
:opcode:`!LOAD_CLASSDEREF`) and in
14361436
:ref:`annotation scopes <annotation-scopes>` within class bodies.
14371437

@@ -1460,8 +1460,8 @@ iterations of the loop.
14601460

14611461
.. opcode:: COPY_FREE_VARS (n)
14621462

1463-
Copies the ``n`` free variables from the closure into the frame.
1464-
Removes the need for special code on the caller's side when calling
1463+
Copies the ``n`` :term:`free (closure) variables <closure variable>` from the closure
1464+
into the frame. Removes the need for special code on the caller's side when calling
14651465
closures.
14661466

14671467
.. versionadded:: 3.11
@@ -1917,10 +1917,10 @@ instructions:
19171917

19181918
.. data:: hasfree
19191919

1920-
Sequence of bytecodes that access a free variable. 'free' in this
1921-
context refers to names in the current scope that are referenced by inner
1922-
scopes or names in outer scopes that are referenced from this scope. It does
1923-
*not* include references to global or builtin scopes.
1920+
Sequence of bytecodes that access a :term:`free (closure) variable <closure variable>`.
1921+
'free' in this context refers to names in the current scope that are
1922+
referenced by inner scopes or names in outer scopes that are referenced
1923+
from this scope. It does *not* include references to global or builtin scopes.
19241924

19251925

19261926
.. data:: hasname

Doc/library/functions.rst

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -678,9 +678,10 @@ are always available. They are listed here in alphabetical order.
678678
``__builtins__`` dictionary into *globals* before passing it to :func:`exec`.
679679

680680
The *closure* argument specifies a closure--a tuple of cellvars.
681-
It's only valid when the *object* is a code object containing free variables.
682-
The length of the tuple must exactly match the number of free variables
683-
referenced by the code object.
681+
It's only valid when the *object* is a code object containing
682+
:term:`free (closure) variables <closure variable>`.
683+
The length of the tuple must exactly match the length of the code object'S
684+
:attr:`~codeobject.co_freevars` attribute.
684685

685686
.. audit-event:: exec code_object exec
686687

Doc/library/symtable.rst

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -167,11 +167,12 @@ Examining Symbol Tables
167167

168168
.. method:: get_nonlocals()
169169

170-
Return a tuple containing names of nonlocals in this function.
170+
Return a tuple containing names of explicitly declared nonlocals in this function.
171171

172172
.. method:: get_frees()
173173

174-
Return a tuple containing names of free variables in this function.
174+
Return a tuple containing names of :term:`free (closure) variables <closure variable>`
175+
in this function.
175176

176177

177178
.. class:: Class

Doc/library/types.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,7 @@ Standard names are defined for the following types:
199199
.. data:: CellType
200200

201201
The type for cell objects: such objects are used as containers for
202-
a function's free variables.
202+
a function's :term:`closure variables <closure variable>`.
203203

204204
.. versionadded:: 3.8
205205

Doc/reference/datamodel.rst

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -561,8 +561,9 @@ Special read-only attributes
561561
in which the function was defined.
562562

563563
* - .. attribute:: function.__closure__
564-
- ``None`` or a :class:`tuple` of cells that contain bindings for the
565-
function's free variables.
564+
- ``None`` or a :class:`tuple` of cells that contain bindings for the names specified
565+
in the :attr:`~codeobject.co_freevars` attribute of the function's
566+
:attr:`code object <function.__code__>`.
566567

567568
A cell object has the attribute ``cell_contents``.
568569
This can be used to get the value of the cell, as well as set the value.
@@ -1238,10 +1239,14 @@ Special read-only attributes
12381239

12391240
* - .. attribute:: codeobject.co_cellvars
12401241
- A :class:`tuple` containing the names of :ref:`local variables <naming>`
1241-
that are referenced by nested functions inside the function
1242+
that are referenced from at least one :term:`nested scope` inside the function
12421243

12431244
* - .. attribute:: codeobject.co_freevars
1244-
- A :class:`tuple` containing the names of free variables in the function
1245+
- A :class:`tuple` containing the names of
1246+
:term:`free (closure) variables <closure variable>` that a :term:`nested scope`
1247+
references in an outer scope. See also :attr:`function.__closure__`.
1248+
1249+
Note: references to global and builtin names are *not* included.
12451250

12461251
* - .. attribute:: codeobject.co_code
12471252
- A string representing the sequence of :term:`bytecode` instructions in

Doc/reference/executionmodel.rst

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ If a name is bound in a block, it is a local variable of that block, unless
9090
declared as :keyword:`nonlocal` or :keyword:`global`. If a name is bound at
9191
the module level, it is a global variable. (The variables of the module code
9292
block are local and global.) If a variable is used in a code block but not
93-
defined there, it is a :dfn:`free variable`.
93+
defined there, it is a :term:`free variable`.
9494

9595
Each occurrence of a name in the program text refers to the :dfn:`binding` of
9696
that name established by the following name resolution rules.
@@ -330,6 +330,9 @@ enclosing namespace, but in the global namespace. [#]_ The :func:`exec` and
330330
:func:`eval` functions have optional arguments to override the global and local
331331
namespace. If only one namespace is specified, it is used for both.
332332

333+
.. XXX(ncoghlan) above is only accurate for string execution. When executing code objects,
334+
closure cells may now be passed explicitly to resolve co_freevars references.
335+
Docs issue: https://github.com/python/cpython/issues/122826
333336
334337
.. _exceptions:
335338

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Clarified the dual usage of the term "free variable" (both the formal
2+
meaning of any reference to names defined outside the local scope, and the
3+
narrower pragmatic meaning of nonlocal variables named in ``co_freevars``).

0 commit comments

Comments
 (0)