New submission from Andrew Barnert:
In #24129, the wording describing class local bindings in 4.2.2 "Resolution of
names" was changed for Python 3.4, 3.5, and 3.6. The new version is a lot
clearer for classes--but now it's misleading for `exec`/`eval`.
---
> Class definition blocks and arguments to exec() and eval() are
> special in the context of name resolution. A class definition is...
... and then proceeds to explain how class lookup works, without ever
mentioning `exec` and `eval`. This implies that they work the same way as
classes, but of course that's not true:
i = 'global'
def f():
i = 'nonlocal'
class C:
print(i)
i = 'local'
print(i)
f()
That prints `global`, then `local`. But with `exec`:
i = 'global'
def f():
i = 'nonlocal'
exec("print(i)\ni = 'local'\nprint(i)\n")
f()
That prints `nonlocal` then `local`.
I think just putting a paragraph break between the first sentence and the rest
of the paragraph might be sufficient to avoid the confusion here. Or just
removing any mention of `eval` and `exec`. If not, this probably needs a new
one-liner paragraph saying something like "Arguments to `exec()` and `eval()`
are also special, as described later."
---
Meanwhile, if you keep reading, you'll eventually find that `exec` is described
in a later section, 4.2.4 "Interaction with dynamic features", but that's
_also_ misleading:
> The eval() and exec() functions do not have access to the full
> environment for resolving names. Names may be resolved in the
> local and global namespaces of the caller. Free variables are not
> resolved in the nearest enclosing namespace, but in the global
> namespace.
If that were true, the `exec` example would have printed `global`, right?
I'm pretty sure that what's going on here is that `exec` implicitly calls
`locals()` (or, rather, the C-API equivalent), which constructs a locals dict
on demand, which, only if you're inside a function block, includes not just the
currently-bound fast locals, but _also_ the cell_contents of the
currently-bound free variables. So, as far as `exec` is concerned, `i` is not
an unbound local, or a free variable, but a local, which is bound to the
`'nonlocal'` cell value of `i` at the time `exec` was called.
Which means the following actually _does_ print `global`:
i = 'global'
def f():
exec("print(i)\ni = 'local'\nprint(i)\n")
i = 'nonlocal'
f()
I have no idea how to make this clear. Maybe the simplest is to not try to give
a full explanation here, and instead punt to the `locals()` function
definition? Maybe something like this:
> The `eval()` and `exec()` functions do not have access to the full
> environment for resolving names, but rather to the approximation of that
> environment as constructed by the `locals()` function. Free variables that
> are not captured as locals are not resolved in the nearest enclosing
> namespace, but in the global...
... and from there, the same as the current paragraph.
----------
assignee: docs@python
components: Documentation
messages: 259073
nosy: abarnert, docs@python
priority: normal
severity: normal
status: open
title: New misleading wording in execution model documenation
_______________________________________
Python tracker <[email protected]>
<http://bugs.python.org/issue26225>
_______________________________________
_______________________________________________
Python-bugs-list mailing list
Unsubscribe:
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com