python / cpython

The Python programming language
https://www.python.org
Other
63.19k stars 30.26k forks source link

Tutorial on Python Scopes and Namespaces uses confusing 'read-only' terminology #70636

Open 652782da-b5f3-46b2-ae1b-1f73662bb759 opened 8 years ago

652782da-b5f3-46b2-ae1b-1f73662bb759 commented 8 years ago
BPO 26449
Nosy @birkenfeld, @rhettinger, @mjpieters, @ezio-melotti

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: ```python assignee = None closed_at = None created_at = labels = ['docs'] title = "Tutorial on Python Scopes and Namespaces uses confusing 'read-only' terminology" updated_at = user = 'https://github.com/mjpieters' ``` bugs.python.org fields: ```python activity = actor = 'holdenweb' assignee = 'docs@python' closed = False closed_date = None closer = None components = ['Documentation'] creation = creator = 'mjpieters' dependencies = [] files = [] hgrepos = [] issue_num = 26449 keywords = [] message_count = 6.0 messages = ['260933', '260946', '260947', '260985', '260996', '260998'] nosy_count = 6.0 nosy_names = ['georg.brandl', 'rhettinger', 'holdenweb', 'mjpieters', 'ezio.melotti', 'docs@python'] pr_nums = [] priority = 'normal' resolution = None stage = None status = 'open' superseder = None type = None url = 'https://bugs.python.org/issue26449' versions = [] ```

652782da-b5f3-46b2-ae1b-1f73662bb759 commented 8 years ago

From the 9.2. Python Scopes and Namespace section:

If a name is declared global, then all references and assignments go directly to the middle scope containing the module’s global names. To rebind variables found outside of the innermost scope, the nonlocal statement can be used; if not declared nonlocal, those variable are read-only (an attempt to write to such a variable will simply create a new local variable in the innermost scope, leaving the identically named outer variable unchanged).

This terminology is extremely confusing to newcomers; see https://stackoverflow.com/questions/35667757/read-only-namespace-in-python for an example. Variables are never read-only. The parent scope name simply is *not visible*, which is an entirely different concept. Can this section be re-written to not use the term 'read-only'?

rhettinger commented 8 years ago

FWIW, the learners in my Python classes seem to find the words "read-only" to be helpful. Also, I think "not visible" conveys the wrong mental model ("shadowed" being a little more accurate).

I also disagree with saying that "variables are never read-only". In fact, unless declared "nonlocal", the namespace for the nested scope can't be written to; likewise, we also have dict proxies in classes that are specifically designed to be read-only; further, there are many read-only attributes in Python.

The current paragraph is succinct and accurate. That said, there is no doubt that creative people can find ways to misread it, so I think there is room to add an extra paragraph that elaborates on the rules:

1) variable *lookups* will search from locals to nested scopes to globals to builtins, stopping at the first match or raising NameError if not found; and,

2) variable *writes* always go into locals unless explicitly declared as being in another namespace with "nonlocal" or "global".

The docs can't smooth this over by changing a single misinterpreted word. One way or another, either in the tutorial or in a FAQ, users need to learn why x=1 doesn't write to an enclosing scope without a namespace declaration and why self.x+=1 can read a class variable, increment the value, and then write to an instance variable. Learning this is fundamental to understanding the language and it can't be glossed over by saying that the word "read-only" was confusing. Everyone gets what "read-only" means; instead, the challenge is to grapple with what the rules are and why the language behaves this way.

ezio-melotti commented 8 years ago

I agree with Raymond. IMHO the term "read-only" does a good job at conveying the fact that you can still access/read the value of the variable but you can't assign to it. "read-only" is about /what/ you can do with the variable, even though it would also be good to clarify /why/ you can only read.

birkenfeld commented 8 years ago

I think rephrasing with "... can only be read" would keep the intended meaning, but avoid the problematic "the namespaces are readonly" meaning.

652782da-b5f3-46b2-ae1b-1f73662bb759 commented 8 years ago

+1 for "... can only be read". read-only can too easily be construed to mean that the variable cannot be set from *anywhere*, even the original scope. Another alternative would be "... is effectively read-only", but "... can only be read" is simpler.

holdenweb commented 8 years ago

I don't agree there is any place for the term "read-only" in this document. A reader who doesn't understand it or seeks clarification is likely to end up at a page like https://en.wikipedia.org/wiki/Read-only. I submit that nowhere except the documentation under discussion are they likely to find any suggestion that a read-only variable can in fact be changed, and hence I regard the discussion as extremely misleading.

Surely it would be better to focus on the fundamental point here, which is that IN THE ABSENCE OF A global OR nonlocal DECLARATION, ASSIGNMENT BINDS IN THE LOCAL NAMESPACE in a function.

If this point is correctly emphasised it should then be relatively easy to explain that in the absence of such an assignment in the function body in question, the standard name resolution algorithm operates, and that the global and non-local declarations change the effect of assignments to operate on the namespace that is identified by the standard name resolution algorithm.

It's too easy to confuse newcomers, and there seems to be general agreement that this piece is confusing. I'll be happy to attempt a rewrite of this section if we can agree on the goals.