简体   繁体   中英

Usage of 'nonlocal' keyword in python

Below program asks for nonlocal keyword with UnboundLocalError: local variable 'balance' referenced before assignment

>>> def make_withdraw(balance):
    """Return a withdraw function with a starting balance."""
    def withdraw(amount):
        if amount > balance:
            return 'Insufficient funds'
        balance = balance - amount
        return balance
    return withdraw

>>> withdraw = make_withdraw(101)
>>> withdraw(25)

But, below program does not give such error when inner function shift refers to lst before assignment as temp = lst[0] .

def shift_left(lst, n):
    """Shifts the lst over by n indices

    >>> lst = [1, 2, 3, 4, 5]
    >>> shift_left(lst, 2)
    >>> lst
    [3, 4, 5, 1, 2]
    """
    assert (n > 0), "n should be non-negative integer"
    def shift(ntimes):
        if ntimes == 0:
            return
        else:
            temp = lst[0]
            for index in range(len(lst) - 1):
                lst[index] = lst[index + 1]         
            lst[index + 1] = temp
            return shift(ntimes-1)
    return shift(n)

How do I understand/compare these two scenarios?

You are never assigning to lst , only to lst[index] . The two concepts are not quite the same thing.

The line:

lst = some_other_value

would rebind the name lst to point to another object. The line:

lst[index] = some_other_value

alters the object referenced by the name lst , by binding a specific index in that sequence to something else. The name lst itself is never altered, so there is no ambiguity here as to what scope that name belongs in.

In Python scoping, only binding operations on the name itself count. Binding operations are not just (direct) assignments, but also include function parameters, function and class definitions, import statements and targets for except .. as , with .. as and the target in for ... in loops. If a name is bound to in a given scope, it is considered local , in all other cases Python looks for the name in a parent scope, with the outermost scope being global .

Assignments to subscriptions (using [...] ) are not binding operations in this context.

See the Naming and binding section of the Python Execution Model documentation, as well as the Short Description of the Scoping Rules? post.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM