Python嵌套函数与nonlocal使用详细介绍
作者:weixin_42576837
理解闭包之前,我们首先需要理解什么是嵌套函数(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_name
的nonlocal
变量,这是因为:
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嵌套函数与nonlocal使用详细介绍的文章就介绍到这了,更多相关Python嵌套函数与nonlocal内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!