【随手记】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

去掉nonlocal,会报错:

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

解释:

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

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

在这段代码中,res 是一个列表,它是在外层函数 treeToDoublyList 中定义的。在 Python 中,列表是可变对象,可以在函数内部通过引用进行修改。

inorder 函数中,虽然 res 是在外层函数中定义的,但是我们只是对其进行修改,没有重新赋值。因此,Python 会默认将 res 视为外层函数中定义的变量,而不是新的局部变量。

nonlocal 不同,nonlocal 用于改变外层函数的局部变量,而不是修改可变对象的值。因此,在使用 nonlocal 时,我们需要明确告诉 Python 我们要修改的是外层函数的局部变量。而对于可变对象,Python 默认会将其视为外层函数的局部变量,因此不需要使用 nonlocal

总结起来,列表等可变对象可以在函数内部进行修改,而不需要使用 nonlocal;而对于需要修改外层函数的局部变量时,我们需要使用 nonlocal 关键字。

目录
相关文章
|
19天前
|
程序员 Python
【随手记】python中各类下划线的作用与功能
【随手记】python中各类下划线的作用与功能
30 0
|
15天前
|
Python
`try-except-finally`是Python异常处理的关键字,用于优雅地处理错误
【6月更文挑战第22天】`try-except-finally`是Python异常处理的关键字,用于优雅地处理错误。示例展示了函数`divide_numbers(a, b)`尝试执行`a/b`,若出现`ZeroDivisionError`,则捕获异常并打印错误信息,最后不论是否异常,都会显示"Division operation completed."。调用该函数分别展示正常除法和除零错误的处理情况。
24 2
|
19天前
|
人工智能 算法 Python
【随手记】python的heapq库的基本用法
【随手记】python的heapq库的基本用法
25 1
|
11天前
|
开发者 Python
在Python中,异常处理通过`try`、`except`、`else`和`finally`关键字进行
【6月更文挑战第26天】在Python中,异常处理通过`try`、`except`、`else`和`finally`关键字进行。基本结构包括尝试执行可能抛出异常的代码,然后指定`except`来捕获特定或任何类型的异常。`else`块在`try`无异常时执行,`finally`块确保无论是否发生异常都会执行,例如用于清理。可以使用`raise`重新抛出异常,而自定义异常则允许创建特定的错误类。这种机制增强了代码的健壮性。
32 7
|
17天前
|
存储 Python 容器
|
18天前
|
消息中间件 安全 开发者
Python global关键字分析
Python 是一种高级编程语言,拥有非常强大的功能和灵活性。在 Python 中,global 关键字可以用于在函数内部修改全局变量的值。本篇技术博客将介绍 global 关键字的使用方法和实现原理。
24 5
|
16天前
|
Python
Python中解包为关键字参数
【6月更文挑战第15天】
14 2
|
19天前
|
Python
【随手记】python语言的else语句在for、while等循环语句中的运用
【随手记】python语言的else语句在for、while等循环语句中的运用
23 2
|
19天前
|
存储 搜索推荐 Python
【随手记】python语法:类属性和实例属性
【随手记】python语法:类属性和实例属性
27 1