python

关注公众号 jb51net

关闭
首页 > 脚本专栏 > python > Python嵌套函数与nonlocal

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

作者:weixin_42576837

这篇文章主要介绍了Python嵌套函数与nonlocal使用,nonlocal关键字与global关键字有点相似,可以对比着理解。nonlocal关键字只能作用域局部变量,且始终找离当前最近的上层局部作用域中的变量

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

嵌套函数

嵌套函数的例子:

#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的优点

缺点

举例

使用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内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文