New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Incorrect (misleading) statement in the execution model documentation #68317
Comments
The documentation on execution model https://docs.python.org/3/reference/executionmodel.html contains the statement x = "xtop"
y = "ytop"
def func():
x = "xlocal"
y = "ylocal"
class C:
print(x)
print(y)
y = 1
func() prints xlocal In case of "normal rules for name resolution" it should rise UnboundLocalError. I suggest replacing the mentioned statement with the following: |
Since no one proposed alternative ideas, I am submitting my proposal as a patch, with the following wording: """ |
Should I invite someone to review the patch or just wait? How the things are organized here? |
In this particular case, just wait (now that you have pinged the issue). Raymond is the most likely person to figure out how to phrase this better, but it isn't obvious what the best way to explain this is. I don't think your explanation is exactly correct, but I don't know enough about how class name resolution is implemented to explain what's wrong with it, I just know it doesn't feel quite right :) (Of course, I might be wrong.) Ping the issue again in a few weeks if there is no action. |
I've left a review. That said, we need to be sure this behavior is intentional. The fact that it skips the "nonlocal" scope(s) smells like a bug to me. |
Eric, thank you for the review. I have incorporated proposed changes in second version of the patch. |
I expect you'll get the same response, especially given potential (though slight) chance for backward-compatibility issues. What I find curious is Guido's reference to "the rule that class bodies don't play the nested That said, it wouldn't hurt to ask on python-dev, particularly in light of that new opcode. |
The "normal rules for name resolution" reference here is referring to the name lookup rules as they existed prior to the introduction of lexical scoping for functions. It's a dated way of describing it, as the current behaviour of functions has now been around long enough that a lot of folks will consider *that* normal, and the module, class and exec scoping rules to be the unusual case (as levkivskyi has here). However, I've spent far too many hours staring at CPython compiler internals to be able to suggest a helpful rewording that will make sense to folks that *haven't* done that, so I'll instead provide the relevant background info to see if others can come up with a concise rewording of the reference docs :) Prior to Python 2.1, Python didn't have closure support, and hence nested functions and classes couldn't see variables in outer scopes at all - they could see their local scope, the module globals, and the builtins. That changed with the introduction of nested scopes as a __future__ import in Python 2.1 and the default behaviour in 2.2: https://www.python.org/dev/peps/pep-0227/ As a result of that change, the compiler now keeps track of "function locals" at compile time, and *emits different code for references to them*. Where early versions of CPython only had LOAD_NAME and LOAD_GLOBAL in the bytecode, these days we now also have LOAD_FAST (function local), LOAD_CLOSURE (function local referenced as a nonlocal), LOAD_DEREF (function nonlocal) and LOAD_CLASSDEREF (class nonlocal). The latter four opcodes will *only* be emitted in a function body - they'll never be emitted for module level code (include the bodies of module level class definitions). If you attempt to reference a function local before a value has been assigned, you'll get UnboundLocalError rather than NameError. The name lookup rules used for execution of class bodies are thus the same ones used for the exec() builtin with two namespace arguments: there is a local namespace where name assignments happen, and name lookups check the local, global and builtin namespaces in that order. The code is executed line by line, so if a name is referenced before it has been assigned locally, then it may find a global or builtin of that name. Classes that are defined inside a function may refer to lexically scoped local variables from the class body, but class variables are not themselves visible to function definitions nested inside a class scope (i.e. method definitions). These rules are also used for module level execution and exec() with a single namespace argument, except that the local namespace and the global namespace refer to the same namespace. |
Eric, the "rule" that classes don't play the nested scopes game is explained at beginning of the same section, but the explanation is "one sided" it only explains that names defined in classes are not visible inside functions. |
Related to http://bugs.python.org/issue19979 and others mentioned there. |
Eric, I have submitted a new version of the patch. Could you please make a review? Nick, it will be interesting to hear your opinion too. I tried to follow such rules:
It turns out that these goals could be achieved by Armin, thank you for the link. It looks like this is a really old discussion. PS: Unfortunately, the diff after reshuffling of the text looks big and cumbersome, in fact the changes are minimal. |
Nick, thank you for a review, I have made a new patch with all the previous comments taken into account. |
It looks like on python-dev (http://www.mail-archive.com/python-dev@python.org/msg88256.html) there is an agreement that this behavior should not be changed (at least not in the nearest future). If there are no more comments/suggestions, then maybe one could accept the latest patch? |
What holds the patch now? Should I do something or just wait? |
I am sorry but I still don't get how things are organized here, so pinging this up. What is the next step? Should I wait for another review? |
Your ping after a month is very appropriate. It looks like yes, this is waiting for another review. Based on the fact that the previous patches were reviewed by core devs and you have responded, I'm moving it to 'commit review', but I haven't looked at the patch myself. |
I merged Ivan's latest patch to 3.4/3.5/default. We're unlikely to ever be able to make these docs completely intuitive (as name resolution is genuinely complex), but Ivan's revisions at least mean we're no longer assuming readers know how the name resolution worked prior to the introduction of lexical scoping, and a couple of tricky cases now have inline examples. I also noticed an existing paragraph in the docs that *I* didn't understand, and filed issue bpo-24796 to cover that. I'm not sure if we should just delete the paragraph, or if we accidentally dropped a compile time error check that didn't have any tests to ensure we were detecting the problem. |
The issue tracker was having issues and didn't automatically register the commits. Links: 3.4: https://hg.python.org/cpython/rev/94e215a5e24b |
Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
bugs.python.org fields:
The text was updated successfully, but these errors were encountered: