Skip to content
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

[doc] clarify documentation of nonlocal #56374

Closed
LukasPetru mannequin opened this issue May 24, 2011 · 9 comments
Closed

[doc] clarify documentation of nonlocal #56374

LukasPetru mannequin opened this issue May 24, 2011 · 9 comments
Labels
3.10 only security fixes 3.11 only security fixes 3.12 bugs and security fixes docs Documentation in the Doc dir easy type-bug An unexpected behavior, bug, or error

Comments

@LukasPetru
Copy link
Mannequin

LukasPetru mannequin commented May 24, 2011

BPO 12165
Nosy @rhettinger, @terryjreedy, @merwok, @eryksun, @nanjekyejoannah, @iritkatriel, @slateny
PRs
  • gh-56374: Clarify nonlocal scope definition #31551
  • 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:

    assignee = None
    closed_at = None
    created_at = <Date 2011-05-24.05:57:36.664>
    labels = ['easy', 'type-bug', '3.9', '3.10', '3.11', 'docs']
    title = '[doc] clarify documentation of nonlocal'
    updated_at = <Date 2022-02-25.06:22:06.473>
    user = 'https://bugs.python.org/LukasPetru'

    bugs.python.org fields:

    activity = <Date 2022-02-25.06:22:06.473>
    actor = 'eryksun'
    assignee = 'none'
    closed = False
    closed_date = None
    closer = None
    components = ['Documentation']
    creation = <Date 2011-05-24.05:57:36.664>
    creator = 'Lukas.Petru'
    dependencies = []
    files = []
    hgrepos = []
    issue_num = 12165
    keywords = ['patch', 'easy']
    message_count = 8.0
    messages = ['136722', '136766', '136834', '136877', '136882', '408404', '413956', '413966']
    nosy_count = 8.0
    nosy_names = ['rhettinger', 'terry.reedy', 'eric.araujo', 'Lukas.Petru', 'eryksun', 'nanjekyejoannah', 'iritkatriel', 'slateny']
    pr_nums = ['31551']
    priority = 'normal'
    resolution = None
    stage = 'patch review'
    status = 'open'
    superseder = None
    type = 'behavior'
    url = 'https://bugs.python.org/issue12165'
    versions = ['Python 3.9', 'Python 3.10', 'Python 3.11']

    Linked PRs

    @LukasPetru
    Copy link
    Mannequin Author

    LukasPetru mannequin commented May 24, 2011

    Can "nonlocal x" declaration also reference global x? I would assume that global scope automatically encloses all other scopes. But the nonlocal keyword seems to exclude global scope. This seems counter-intuitive. (maybe bug in implementation?)

    For example:

    x=0
    
    def count(i):
        nonlocal x; x+=i; return x;

    Checking this code in IDLE gives: SyntaxError: no binding for nonlocal 'x' found. If this is what was intended, maybe it should be more clearly written in the documentation.

    I am coming to Python from Lisp, so I am still learning Python's principles.

    @LukasPetru LukasPetru mannequin added interpreter-core (Objects, Python, Grammar, and Parser dirs) type-bug An unexpected behavior, bug, or error labels May 24, 2011
    @merwok
    Copy link
    Member

    merwok commented May 24, 2011

    @LukasPetru
    Copy link
    Mannequin Author

    LukasPetru mannequin commented May 25, 2011

    Well, I read that text before, but it may be because I am not native english speaker that I interpret the text differently. Let's go through it one step at a time and show me where I am wrong.

    1. The nonlocal statement causes the listed identifiers to refer to previously bound variables in the nearest enclosing scope.
    • I assume here that global scope is an enclosing scope (global encloses everything in the module).
    1. The statement allows encapsulated code to rebind variables outside of the local scope besides the global (module) scope.
    • Here I interpret "besides" as "in addition to".

    Nothing specifically says that global bindings are excluded.

    @rhettinger
    Copy link
    Contributor

    Lukas, I'll fix-up the docs. Thanks for pointing out the deficiency.

    @rhettinger rhettinger added docs Documentation in the Doc dir and removed interpreter-core (Objects, Python, Grammar, and Parser dirs) labels May 25, 2011
    @rhettinger rhettinger self-assigned this May 25, 2011
    @terryjreedy
    Copy link
    Member

    Another problem with the current text is that it fails to exclude enclosing class scopes, and I had to test to be sure they were., and some of the phrasing strikes me as awkward. Here is a possible rewrite.

    "When the definition of a function is nested (enclosed) within the definitions of other functions, its nonlocal scopes are the local scopes of the enclosing functions. The nonlocal statement causes the listed identifiers to refer to names previously bound in nonlocal scopes. If a name is bound in more than one nonlocal scope, the nearest binding is used. If a name is not bound in any nonlocal scope, or if there is no nonlocal scope, a SyntaxError is raised.

    Except for the requirement that the listed indentifiers be previously bound, the nonlocal statement is similar to the global statement. It applies to the entire function body, so it cannot follow any local bindings of the same names."

    My main change is to first unambiguously define nonlocal scopes and continue from there.

    @terryjreedy terryjreedy changed the title Does nonlocal include global? Nonlocal does not include global; clarify doc May 25, 2011
    @rhettinger rhettinger removed their assignment Jul 12, 2013
    @iritkatriel
    Copy link
    Member

    The doc has been updated by now and mentions "excluding globals".
    I'm changing the title to reflect Terry's last comment.

    One comment on his suggestion: I would remove/change "the nonlocal statement is similar to the global statement" because it's not obvious in what way it is similar just from the sentence, I think this is more confusing then helpful.

    @iritkatriel iritkatriel added easy 3.9 only security fixes 3.10 only security fixes 3.11 only security fixes labels Dec 12, 2021
    @iritkatriel iritkatriel changed the title Nonlocal does not include global; clarify doc [doc] clarify documentation of nonlocal Dec 12, 2021
    @rhettinger
    Copy link
    Contributor

    I think this is more confusing then helpful.

    I concur.

    @eryksun
    Copy link
    Contributor

    eryksun commented Feb 25, 2022

    Another problem with the current text is that it fails to exclude
    enclosing class scopes

    The nonlocal statement is only disallowed in module code (i.e. "exec" compilation mode) because it can never be nested. It's allowed in a class definition that has an outer function scope. A class body itself is never a nonlocal scope; it just has access to them. Here's a slightly modified version that includes class definitions:

    "When the definition of a function or class is nested (enclosed) within the definitions of other functions, its nonlocal scopes are the local scopes of the enclosing functions. The nonlocal statement causes the listed identifiers to refer to names previously bound in nonlocal scopes. If a name is bound in more than one nonlocal scope, the nearest binding is used. If a name is not bound in any nonlocal scope, or if there is no nonlocal scope, a SyntaxError is raised.

    The nonlocal statement applies to the entire scope of a function or class body. A SyntaxError is raised if a variable is used or assigned to prior to its nonlocal declaration in the scope."

    @ezio-melotti ezio-melotti transferred this issue from another repository Apr 10, 2022
    @iritkatriel iritkatriel added 3.12 bugs and security fixes and removed 3.9 only security fixes labels Mar 1, 2023
    terryjreedy added a commit to terryjreedy/cpython that referenced this issue Mar 18, 2024
    Redefine 'nonlocal scopes' in a way that excludes class scopes.
    Rearrange the rest of the doc.  Add "Programmer's note".
    terryjreedy added a commit that referenced this issue Mar 19, 2024
    Define 'nonlocal scopes' in a way that excludes class scopes.
    Rearrange the rest of the doc.  Add "Programmer's note".
    miss-islington pushed a commit to miss-islington/cpython that referenced this issue Mar 19, 2024
    Define 'nonlocal scopes' in a way that excludes class scopes.
    Rearrange the rest of the doc.  Add "Programmer's note".
    (cherry picked from commit 025ef7a)
    
    Co-authored-by: Terry Jan Reedy <tjreedy@udel.edu>
    terryjreedy pushed a commit that referenced this issue Mar 19, 2024
    Define 'nonlocal scopes' in a way that excludes class scopes.
    Rearrange the rest of the doc.  Add "Programmer's note".
    
    (cherry picked from commit 025ef7a)
    Co-authored-by: Terry Jan Reedy <tjreedy@udel.edu>
    @terryjreedy
    Copy link
    Member

    Not backported to 3.11 due to merge conflict.

    vstinner pushed a commit to vstinner/cpython that referenced this issue Mar 20, 2024
    Define 'nonlocal scopes' in a way that excludes class scopes.
    Rearrange the rest of the doc.  Add "Programmer's note".
    adorilson pushed a commit to adorilson/cpython that referenced this issue Mar 25, 2024
    Define 'nonlocal scopes' in a way that excludes class scopes.
    Rearrange the rest of the doc.  Add "Programmer's note".
    diegorusso pushed a commit to diegorusso/cpython that referenced this issue Apr 17, 2024
    Define 'nonlocal scopes' in a way that excludes class scopes.
    Rearrange the rest of the doc.  Add "Programmer's note".
    Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
    Labels
    3.10 only security fixes 3.11 only security fixes 3.12 bugs and security fixes docs Documentation in the Doc dir easy type-bug An unexpected behavior, bug, or error
    Projects
    None yet
    Development

    No branches or pull requests

    5 participants