目录
- 变量作用域
- 变量?字典?
- 获取变量字典
- 变量遮蔽
- 解决方法:
- 方法1:使用globals访问全局变量
- 方法2:在函数中声明全局变量
- 局部函数
- 封闭函数返回局部函数
- 代码演示
- 另一种写法
- 局部函数的遮蔽
- 问题如图:
- 解决方法:
- global与nonlocal的总结
理解变量作用域
变量字典
处理局部变量遮蔽全局变量
理解局部函数
定义、使用局部函数
封闭函数返回局部函数
局部函数的变量遮蔽
变量作用域
根据定义变量的位置,变量的作用域有两种:
局部变量: 在函数中定义的变量包括参数,都被称为局部变量。
全局变量: 在函数外面、全局范围内定义的变量,被称为全局变量。
变量?字典?
不管是全局范围,还是局部范围,这些变量和它们的值的就像一个“看不见”的字典:
其中变量名就是字典的key
变量值就是字典的value。
获取变量字典
globals(): 该函数返回全局范围内所有变量组成的“变量字典”。
locals(): 该函数返回当前局部范围内所有变量组成的“变量字典”。
vars(object): 获取指定对象的范围内所有变量组成的“变量字典”,如果不传入object参数,vars()和locals()的作用完全相同。
解释:为什么在全局打印globals和locals的结果一样
如图:
locals 是获取当前范围的所有局部变量,因此如果在全局范围调用locals(),它返回全部的全局变量。
简单来说,在全局范围内(在全局范围内,它的当前范围就是全局),用globals() 和 locals() 两个函数的效果是一样的。
globals()
注意,在函数内部调用globals()函数仍然只能获取到全局变量,而无法获取到局部变量
locals()
对于局部变量,应该使用locals()函数来获取。locals()函数返回一个字典,其中包含了当前作用域内的所有变量,包括局部变量
变量遮蔽
全局变量默认可以在所有函数内访问,
如果在函数中定义了与全局变量同名的变量,此时就会发生局部变量遮蔽(hide)全局变量的情形
如图:
解决方法:
方法1:使用globals访问全局变量
希望在全局变量的地方用全局变量,在局部变量的地方,还用局部变量,
就是在全局变量中,name是aaaaaa,在局部变量中,name是bbbbbbb。
可通过globals()在函数中访问被遮蔽的全局变量
方法2:在函数中声明全局变量
在函数中可使用global语句来声明全局变量,即可避免重新定义局部变量,而是对全局变量赋值。
注意:如果要在函数内对全局变量赋值,那就需要使用global来声明全局变量
就是在函数里面操作同名的name变量时,是在操作全局变量的那个name,而不是方法1的重新定义name变量。
=================================================
局部函数
放在函数体内定义的函数称为局部函数。
就是函数里面的函数,就叫局部函数
在默认情况下,局部函数对外部是隐藏的,局部函数只能在其封闭(enclosing)函数内使用。
封闭函数返回局部函数
封闭函数可以返回局部函数,以便程序在其他作用域中使用局部函数。
如果封闭函数没有将局部函数返回出来,那么局部函数将只能在封闭函数内部调用
代码演示
需求:在info函数中返回局部函数bar,以便程序在其他作用域中使用局部函数bar
原本bar函数只能在 info函数里面调用,现在这个操作,就可以在info函数外调用到这个bar函数了,因为info函数把bar函数给弄成返回值返回出来了。
这个 info 就是封闭函数,也叫外部函数。
解释:
另一种写法
在info函数外调用局部函数bar的写法
局部函数的遮蔽
局部函数内的变量也会遮蔽它所在的封闭函数的局部变量
局部函数为了避免遮蔽所在封闭函数的局部变量,可使用nonlocal进行声明
这个遮蔽的意思,我个人把它理解为把别人的变量给弄没了。不是覆盖的意思。而是弄没了。
问题如图:
如图:这里的遮蔽,就是原本我可以在 info内部函数 里面调用到test这个封闭函数(外部函数) 的 name变量,此时的name变量是属于 test函数的局部变量。
但是如果我在info 函数里面定义一个相同名字的name变量,那么就会出现info函数的name变量遮蔽到test函数的name变量。
所以在info函数第一行引用name,原本是可以引用到test函数的name变量,现在因为被遮蔽了,所以显示这个name引用未被解析,简单理解为没有这个name变量。
解决方法:
局部函数为了避免遮蔽所在封闭函数的局部变量,可使用nonlocal进行声明
global与nonlocal的总结
nonlocal和前面介绍的global功能大致相似:都用于避免变量被遮蔽
区别只是global用于声明访问全局变量,而nonlocal用于声明访问局部函数所在的封闭函数之内的局部变量