当前位置:   article > 正文

【随手记】python中的nonlocal关键字

【随手记】python中的nonlocal关键字

看一段代码,下边这段代码用于将二叉搜索树转换为升序排列的双向链表:

"""
# Definition for a Node.
class Node:
    def __init__(self, val, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right
"""
class Solution:
    def treeToDoublyList(self, root: 'Node') -> 'Node':
        if not root:
            return root

        # 递归函数,用于中序遍历和连接节点
        def recursion(root):
            nonlocal prev, head

            if root:
                # 递归遍历左子树
                recursion(root.left)

                # 将当前节点与前一个节点连接起来
                if prev:
                    prev.right = root
                    root.left = prev
                else:
                    # 当前节点是最左的节点,将其赋值给head
                    head = root
                prev = root

                # 递归遍历右子树
                recursion(root.right)

        prev = None  # 前一个节点
        head = None  # 头节点
        recursion(root)

        # 将头节点和尾节点连接起来,形成循环双向链表
        head.left = prev
        prev.right = head
        return head
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41

去掉nonlocal,会报错:

UnboundLocalError: cannot access local variable 'prev' where it is not associated with a value
  • 1

解释:

nonlocal 是Python中的关键字,用于声明一个嵌套函数中的变量是来自于其外部函数的局部作用域,而不是来自于全局作用域。
在这段代码中,prevhead 是在 recursion 函数之外定义的变量。然而,我们需要在 recursion 函数中对它们进行修改。为了在 recursion 函数中能够访问并修改这些变量,我们使用 nonlocal 关键字来声明它们。
这样,在 recursion 函数中对 prevhead 的修改将会影响到它们在 treeToDoublyList 方法中的值。这使得我们能够在 recursion 函数中正确地处理节点的连接和循环链表的生成。

再看下边一段二叉树中序遍历的代码:

class Solution:
    def inorderSearch(self, root: 'Node') -> 'Node':
        if not root:
            return None

        res = []
        def inorder(node):
            if node:
                inorder(node.left)
                res.append(node.val)
                inorder(node.right)
        
        inorder(root)
        return res
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

res同样是在外层函数中定义然后在内层函数中使用,为什么这里没有加上nonlocal也没有报错?

在这段代码中,res 是一个列表,它是在外层函数 treeToDoublyList 中定义的。在 Python 中,列表是可变对象,可以在函数内部通过引用进行修改。
inorder 函数中,虽然 res 是在外层函数中定义的,但是我们只是对其进行修改,没有重新赋值。因此,Python 会默认将 res 视为外层函数中定义的变量,而不是新的局部变量。
nonlocal 不同,nonlocal 用于改变外层函数的局部变量,而不是修改可变对象的值。因此,在使用 nonlocal 时,我们需要明确告诉 Python 我们要修改的是外层函数的局部变量。而对于可变对象,Python 默认会将其视为外层函数的局部变量,因此不需要使用 nonlocal
总结起来,列表等可变对象可以在函数内部进行修改,而不需要使用 nonlocal;而对于需要修改外层函数的局部变量时,我们需要使用 nonlocal 关键字。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Monodyee/article/detail/71105
推荐阅读
相关标签
  

闽ICP备14008679号