亲宝软件园·资讯

展开

Python嵌套函数与nonlocal

weixin_42576837 人气:0

理解闭包之前,我们首先需要理解什么是嵌套函数(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

加载全部内容

相关教程
猜你喜欢
用户评论