使用' nonlocal' python中的关键字

时间:2015-05-22 13:36:07

标签: python python-3.x scope

以下程序会询问nonlocal

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)

但是,如果内部函数shift在赋值为lst之前引用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)

我如何理解/比较这两种情况?

1 个答案:

答案 0 :(得分:1)

您永远不会分配到lst,只会分配到lst[index]。这两个概念并不完全相同。

该行:

lst = some_other_value

将重新绑定名称lst以指向另一个对象。这一行:

lst[index] = some_other_value

通过将该序列中的特定索引绑定到其他内容来更改名称lst引用的对象。名称lst本身永远不会被更改,因此这里没有关于该名称所属范围的歧义。

在Python范围界定中,只对名称本身的绑定操作计数。绑定操作不仅仅是(直接)分配,还包括importexcept .. as的函数参数,函数和类定义,with .. as语句和目标以及for ... in中的目标循环。如果名称在给定范围内绑定,则将其视为 local ,在所有其他情况下,Python在父作用域中查找名称,最外层作用域为global

subscriptions 的分配(使用[...])在此上下文中不是绑定操作。

请参阅Python执行模型文档的Naming and binding section以及 Short Description of the Scoping Rules? 帖子。