nonlocal在python中的用法

2024年 1月 31日 77.3k 0

今天我们要讲的是关于作用域的关键词:nonlocal

太长有空再看,先来看个大概

  • nonlocal 的面貌
  • nonlocal 多了解一点
  • 如何工作
  • 与global有关系吗?
  • 要注意点啥

nonlocal的面貌

图片[1]-nonlocal在python中的用法-不念博客

闪亮登场

让我们从故事开始讲起。

有一个古老的图书馆,每一本书都是一个函数,书架就像是函数的作用域,而 nonlocal 关键词则是一个特殊的通行证,它允许你在一个函数里修改另一个嵌套函数中的变量。

但这不是随随便便就能做的事, nonlocal 声明的是那些既不属于局部作用域,也不属于全局作用域的变量,它们处于嵌套函数的中间地带。

在 Python 的世界里,函数可以嵌套函数,就像盒子套盒子一样。通常情况下,每个盒子(函数)里的东西(变量)只能在自己的盒子里被找到和修改。

但有时候,内层的小盒子想要去改变外层盒子里的某个东西,这时候就需要用到 nonlocal 这个法术了。

nonlocal的本质

nonlocal 的存在像是一条隐形的桥,连接着嵌套函数之间的变量。

要理解 nonlocal ,得先搞清楚Python里的作用域和变量。简单来说,作用域决定了在哪些地方你可以访问哪些变量。(我们马上就会说什么是作用域~)

在Python中,函数就像是一个小盒子,里面定义的变量默认只在盒子里有效,外面是访问不到的。

nonlocal 的魅力在于它提供了一种微妙的方式来修改嵌套作用域中的变量。

这在编写闭包或者装饰器等高级功能时特别有用。它让变量的作用域既不是那么封闭也不是无限开放,而是在一个合适的层级中进行操作。

nonlocal多了解一点

必须在外层非全局作用域中定义

nonlocal 关键字的一个核心特性是,它声明的变量必须已经存在于外层函数的作用域中,而不能是全局作用域或当前作用域中新定义的。

这就像是在一个家族聚会中,你只能通过 nonlocal 声明去引用那些已经到场的家族成员(变量),而不是那些根本没来(未定义)或者是全家族都知道的大名人物(全局变量)。

不能用于全局变量或最外层函数

nonlocal 的设计初衷是为了解决嵌套函数间变量共享的问题,而全局变量本来就对所有函数可见,没有必要用 nonlocal 来声明。

如果你试图在最外层函数中使用 nonlocal 声明变量,Python 会抛出一个语法错误,因为 nonlocal 需要一个封闭的函数作用域来寻找相应的变量,而最外层函数没有“外层”了。

def outer_function():
    nonlocal x
    x = 10

outer_function()

报错信息:

SyntaxError: no binding for nonlocal 'x' found

适用于多层嵌套场景

nonlocal 在多层嵌套的函数场景下显得尤为重要。在这种情况下,如果内层函数需要修改外层函数(但不是全局作用域)中定义的变量, nonlocal 就能派上用场。

nonlocal 促成了一种在函数间共享变量的机制,这大大增强了函数内部的互动性和灵活性。

通过这种方式,嵌套函数不再是孤立的个体,而是能够相互影响和协作,共同完成更复杂的任务。

def outer_function():
    shared_variable = 0

    def inner_function1():
        nonlocal shared_variable
        shared_variable += 1
        print("Inner Function 1: shared_variable =", shared_variable)

    def inner_function2():
        nonlocal shared_variable
        shared_variable += 2
        print("Inner Function 2: shared_variable =", shared_variable)

    inner_function1()
    inner_function2()

    print("Outer Function: shared_variable =", shared_variable)

outer_function()

输出:

Inner Function 1: shared_variable = 1
Inner Function 2: shared_variable = 3
Outer Function: shared_variable = 3

nonlocal如何工作

来看一个简单的例子:

pythonCopy codedef outer():
    x = "local"
    def inner():
         nonlocal  x  # 这里我们使用 nonlocal 关键字
        x = " nonlocal "
        print("内部:", x)
    
    inner()
    print("外部:", x)

outer()

在这个例子中,inner 函数中的 nonlocal 声明允许我们修改 outer 函数中的 x 变量。

当我们调用 outer 函数时,它首先设置 x 为 “local” ,然后调用 inner函数。

inner 函数中的nonlocal x声明意味着当我们在 inner 中改变 x的值时,实际上是在改变outer函数作用域中的x

因此,输出会是:

内部:  nonlocal 
外部:  nonlocal 

与隔壁的global聊聊

图片[2]-nonlocal在python中的用法-不念博客

nonlocal与global的区别

简单来说, global用于在局部作用域中修改全局变量,而 nonlocal 则用于修改嵌套作用域中的变量。

如果Python是一个国度,那么 global 就像是国王的法令,可以在任何地方发挥作用;

而 nonlocal 更像是一个地方领主的权力,它只在自己的领地内有效。

global 的魔法

global 关键字用来在函数或其他局部作用域中声明全局变量。

x = "这是全局的"

def my_function():
     global  x  # 使用  global  关键字声明
    x = "全局变量被修改了"

my_function()
print(x)  # 输出: "全局变量被修改了"

nonlocal的巫术

nonlocal 关键字的作用则更为精细。它用于嵌套函数中,允许你修改外层函数(非全局作用域)中的变量。

def outer():
    y = "外层变量"

    def inner():
         nonlocal  y  # 使用  nonlocal  关键字声明
        y = "外层变量被修改了"
    
    inner()
    print(y)  # 输出: "外层变量被修改了"

outer()

使用nonlocal的注意点

明确存在的变量

nonlocal 声明的变量必须已经在外层函数的作用域中存在。

这就像你不能指派一个不存在的人去完成任务一样。

非全局作用域

nonlocal 不能用于全局变量或在包含 nonlocal 声明的最外层函数中。

它专门设计用来在嵌套函数之间共享变量。

避免混淆

在使用 nonlocal 时,要确保你没有在同一作用域内重新定义相同名称的变量,这会引起混淆并可能导致不可预料的结果。

这就像在一个房间里不能有两个完全相同的标识,以免造成混淆。

不要过度使用

虽然 nonlocal 提供了一种修改外层变量的便捷方式,但过度使用可能会使代码变得难以理解和维护,特别是在复杂的嵌套函数中。

每次使用 nonlocal 时,都要考虑是否有更简单的设计或方法可以达到同样的目的。

是否推荐使用 nonlocal

nonlocal 的使用取决于具体的编程需求和场景。

在某些情况下,如闭包或装饰器等高级编程模式中, nonlocal 是实现特定功能的必要工具。在这些场景下, nonlocal 的使用是推荐的,因为它提供了一种优雅的解决方案。

然而,如果可以通过更简单的设计达到同样的目的,比如使用类(面向对象编程)来管理状态,那么优先考虑这些方法可能更佳。

过度或不恰当地使用 nonlocal 可能会使代码难以理解和维护,特别是对于不熟悉嵌套作用域概念的新手来说。

相关文章

JavaScript2024新功能:Object.groupBy、正则表达式v标志
PHP trim 函数对多字节字符的使用和限制
新函数 json_validate() 、randomizer 类扩展…20 个PHP 8.3 新特性全面解析
使用HTMX为WordPress增效:如何在不使用复杂框架的情况下增强平台功能
为React 19做准备:WordPress 6.6用户指南
如何删除WordPress中的所有评论

发布评论