“非本地”变量是否总是从外部循环继承,即使在递归调用中?

问题描述

我写了一些代码,最近在编写函数函数时遇到了“非本地”的需要(在处理递归时遇到了这个)。

例如:

def swapPairs(head): 
    head = None

    def helper(node): 
        nonlocal head 
        ...
        head= nex.next 
        return helper(node.next) 

我的问题很简单,因为我们调用递归函数 helper(node.next) ,然后循环回到 nonlocal head - head 是否采用 None 的值(由于非本地头)?或者它是否保留了 head = nex.next,它在之前的递归调用中分配给了它?

所以我试图了解 'nonlocal head' 是否会导致 head 始终采用它在外部函数中分配给它的任何值,或者情况并非如此?相反,它只是在内部函数中初始化 head 的一种方法,因此它仅通过采用外部函数中定义的初始值来启动。

解决方法

nonlocalglobal 声明用于词法范围——松散地说,它们只关心源代码布局。

def swapPairs(head): 
    head = None         # `head` in lexically outer scope          <═╗
                        #                                            ║
    def helper(node):   #                                            ║
        nonlocal head   # nonlocal `head` for inner lexical scope  >═╣
        ...             #                                            ║
        head= nex.next  # nonlocal applies to every use            >═╝
        return helper(node.next)

值得注意的是,作用域与代码的运行时嵌套完全无关;它不关心 helper 是否被 swapPairs、一系列 helper 或一些不相关的函数调用:head 中的名称 helper 是完全等效的到 head 中的名称 swapPairs

这意味着 head 中的 def helper总是引用定义 headswapPairs 调用中的 def helper。一旦对 helper 的第一次调用分配了 head = nex.next,它改变了 head 内的 swapPairs ,随后对 helper 的调用将看到 (并修改)这个新值。