[docs] [issue26225] New misleading wording in execution model documenation
Andrew Barnert
report at bugs.python.org
Wed Jan 27 19:01:28 EST 2016
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 at python
components: Documentation
messages: 259073
nosy: abarnert, docs at python
priority: normal
severity: normal
status: open
title: New misleading wording in execution model documenation
_______________________________________
Python tracker <report at bugs.python.org>
<http://bugs.python.org/issue26225>
_______________________________________
More information about the docs
mailing list