Python嵌套函数与nonlocal使用详细介绍

 更新时间:2022年09月07日 16:13:28   作者:weixin_42576837  
这篇文章主要介绍了Python嵌套函数与nonlocal使用,nonlocal关键字与global关键字有点相似,可以对比着理解。nonlocal关键字只能作用域局部变量,且始终找离当前最近的上层局部作用域中的变量

理解闭包之前,我们首先需要理解什么是嵌套函数(nested functions)以及非局部(nonloca)关键字

嵌套函数

  • 在另一个函数中定义的函数称为嵌套函数。
  • 嵌套函数可以访问 这个封闭范围域内的 变量。
  • 在python中,这些非局部变量只可以在他们的作用域范围内访问。

嵌套函数的例子:

#Python program to illustrate
#nested functions
def outerFunction(text):
    text = text
    #该函数定义在函数之内,作为一个内部函数
    def innerFunction():
        print(text)
    #out函数中,调用这个内部函数
    innerFunction()
if __name__ == '__main__':
    outerFunction('Hey !')

嵌套函数中变量的范围

在一个函数中访问全局变量之前已经说过了,但是怎么在一个内部函数中访问外部函数的变量?

def f1():
    #f1的变量
    s = 'hello'
    def f2():
        #f2()内部使用f1的变量
        print(s)
    f2()
f1()

这种访问方式和 函数内访问全局变量很类似。

现在我想要在内部函数改变外部函数的变量要怎么做?

def f1():
    #f1的变量
    s = 'hello'
    def f2():
        #f2()内部试图改变f1的变量
        s = 'hi hi hi'
        print(s)
    f2()
    print(s)
#调用f1()
f1()

f2()内部通过s = 'hi hi hi' 试图将外部函数的变量值s改变。

但是其实是在f2()内部重新创建了一个新的变量也叫s,所以完全不会对外部的s有影响。

这和函数内部改变全局变量是类似的,不加global,只是创建了一个同名变量。

那么同样使用global行不行?

def f1():
    #f1的变量
    s = 'hello'
    def f2():
        #f2()内部试图使用global改变f1的变量
        global s
        s = 'hi hi hi'	#实际是在f2()中创建了一个全局变量
        print(s)
    f2()
    print(s)
#调用f1()
f1()

结果是完全没有变化的,

global s实际上是在f2()内部声明s是一个全局变量,是整个程序都可以使用的,它和f1()中的s不是同一个。我们可以在函数外输出它:

那么如何通过内部函数改变外部函数的变量值呢?其中一种方法是使用nonlocal关键字:

def f1():
    #f1的变量
    s = 'hello'
    def f2():
        #f2()使用nonlocal改变f1的变量
        nonlocal s
        s = 'hi hi hi'
        print(s)
    f2()
    print(s)
#调用f1()
f1()

在f2()函数内部成功的修改了f1()函数中的变量s的值

nonlocal

nonlocal 关键字被用来在最近的范围域中引用变量, 在局部变量和全局变量上使用不起作用,用于在全局范围和本地局部范围之外的另一个范围内引用变量。nonlocal关键字常常被用在嵌套函数中引用 父函数中的变量。

使用nonlocal的优点

  • 帮助我们访问上层作用域中的变量
  • 引用的变量被重复使用,因此该变量的内存地址也被重复适使用,所以可以将局部变量保存在内存中

缺点

  • nonloca关键字不可以用来引用全局变量和局部变量
  • nonloca关键字只能用在嵌套结构中

举例

使用nonlocal关键字修改父函数中的变量

def foo():
    name = 'hello'
    def  bar():
        nonlocal name #修改父函数的变量
        name = 'hi hi'
        print(name)
    #调用bar()
    bar()
    #父函数foo()内输出name
    print(name)
#调用foo()
foo()

如果使用nonlocal 修改全局变量会怎么样?

#全局变量
global_name = 'hello'
#外部函数
def f1():
    #内部函数
    def f2():
        #使用nonlocal 声明,尝试使用nonlocal 引用全局变量
        nonlocal global_name
        global_name = 'hi hi'#尝试 修改 
        print(global_name)
    
    #掉用f2()
    f2()
f1()
print(global_name)

报错信息显示:没有叫做global_namenonlocal变量,这是因为:

nonlocal是用在嵌套结构中,用来引用父函数中的局部变量的,但是父函数f1()中没有叫做global_name的局部变量,对于函数外部的全局变量global_name来说,使用nonlocal是无法引用的,所以python解释器找不到global_name,自然出错。

多层嵌套中的nonlocal

def f1():
    name = 'f1'
    def f2():
        name = 'f2'
        def f3():
            #nonlocal 修改父函数的变量,即f2()的name
            nonlocal name
            print(name)  #输出f2  使用的是f2中的name
            name = 'f3' #对f2中的name修改
            print(name) #输出f3 修改成功
        f3()
        print(name)#输出f3,虽然是f2中的name,但是在f3中修改了
    f2()
    print(name)#输出f1,f1的name,没有被使用
f1()

所以在多层嵌套的结构成,nonlocal关键字会寻找最近的上层,也就是父函数,而不是更上层的爷爷函数。

嵌套函数中局部变量的重用

def counter():
    #c是局部变量
    c = 0
    def count():
        #使用上层函数中的c
        nonlocal c
        c += 1
        return c
    return count

调用外部counter()函数,正常来说,函数调用结束后,内部的局部变量会被销毁,但是由于counter()内部嵌套的count()使用了nonlocal来使用父函数的局部变量c,所以c是被重用了,即使外层函数调用结束了,c并没有被销毁。

参考:

Python Inner Functions

Python nonlocal Keyword

到此这篇关于Python嵌套函数与nonlocal使用详细介绍的文章就介绍到这了,更多相关Python嵌套函数与nonlocal内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • python strip() 函数和 split() 函数的详解及实例

    python strip() 函数和 split() 函数的详解及实例

    这篇文章主要介绍了 python strip() 函数和 split() 函数的详解及实例的相关资料,需要的朋友可以参考下
    2017-02-02
  • Python实现正则表达式匹配任意的邮箱方法

    Python实现正则表达式匹配任意的邮箱方法

    今天小编就为大家分享一篇Python实现正则表达式匹配任意的邮箱方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-12-12
  • Python将视频转换为图片介绍

    Python将视频转换为图片介绍

    大家好,本篇文章主要讲的是Python将视频转换为图片介绍,感兴趣的同学赶快来看一看吧,对你有帮助的话记得收藏一下,方便下次浏览
    2022-01-01
  • 使用matplotlib画图自定义marker

    使用matplotlib画图自定义marker

    这篇文章主要介绍了使用matplotlib画图自定义marker问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-06-06
  • Python过滤序列元素的方法

    Python过滤序列元素的方法

    这篇文章主要介绍了Python过滤序列元素的方法,文中讲解非常细致,代码帮助大家更好的理解和学习,感兴趣的朋友可以了解下
    2020-07-07
  • Opencv+Python 色彩通道拆分及合并的示例

    Opencv+Python 色彩通道拆分及合并的示例

    今天小编就为大家分享一篇Opencv+Python 色彩通道拆分及合并的示例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-12-12
  • matplotlib 曲线图 和 折线图 plt.plot()实例

    matplotlib 曲线图 和 折线图 plt.plot()实例

    这篇文章主要介绍了matplotlib 曲线图 和 折线图 plt.plot()实例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-04-04
  • django之用户、用户组及权限设置方式

    django之用户、用户组及权限设置方式

    这篇文章主要介绍了django之用户、用户组及权限设置方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-05-05
  • python装饰器原理源码示例分析

    python装饰器原理源码示例分析

    本文由浅入深介绍了python的装饰器,并且通过代码展现了如何自己手写装饰器函数和类装饰器,有需要的朋友可以参考下,希望可以有所帮助
    2021-09-09
  • python实现网上购物系统

    python实现网上购物系统

    这篇文章主要为大家详细介绍了python实现网上购物系统,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-06-06

最新评论