有个朋友问我 nonlocal 的用法,如此,就拿它与global做个对比,更能体现出它的用法。
如果你理解了这几个案例,那么你就懂了其中的区别了。
01 global用法解析
一句话总结:global可以用于任何地方,声明变量为全局变量(声明时不能同时赋值),声明后再修改,则修改了全局变量的值。
用个例子来举证:
(左右滑动查看完整代码)
代码解析:
-
首行定义全局变量num=0。
-
方法f中定义局部变量num=1,且没有global声明,因此与外部的num没有任何关系,因此num1直接输出为1。
-
调用inner函数,函数中声明inner中的变量num绑定为全局变量,即与首行的num为同一变量,且变更为2。
-
由于global声明的变量只在当前方法中生效,因此inner中的声明不能作用于inner以外函数中的变量,就是说inner中的num与f中的num不是同一个变量。而打印num2是在f方法中打印的,因此还是输出1。
-
最后的num0打印的全局变量,由于已经被更新为2,因此输出为2。
结果:
num1:: 1
num2:: 1
num0:: 2
下图为变量更新流程图:
再举个例子巩固一下:
name = 0
def readonly():
name = 10
print("readonly: ", name)
def readwrite():
global name
name = 20
print("readwrite:", name)
global new_name
new_name = 30
readonly()
print("outer1: ", name)
readwrite()
print("outer2: ", name)
print("new_name: ", new_name)
代码解析:
-
首行定义全局变量name=0。
-
调用readonly方法,且方法中定义局部变量name,没有global声明,与外部name没有任何关系,因此打印readonly = 10。
-
同理outer1打印的就是全局变量name,没有受readonly影响,输出0。
-
调用readwrite方法,方法中声明name就是外部的全局变量name,且更新全局变量的值为20,因此打印readwrite为20。
-
方法readwrite中直接声明new_name为全局变量,但是前面并没有定义,这里注意,global即使没有提前定义,也可以作为全局变量使用,因为它可以在任何地方使用。
-
因此outer2的输出是全局变量name,由于被变更为20,因此输出20。
-
而new_name 本身就是全局变量,输出为30。
下图为变量更新流程图:
02 nonlocal解析
一句话概括:nonlocal的作用范围仅对于所在子函数的上一层函数中拥有的局部变量,必须在上层函数中已经定义过,且非全局变量,否则报错。
用一个例子来说明:
count = 0
def outer():
count = 10
def inner():
nonlocal count
count = 20
print("count1:",count)
def inner2():
nonlocal count
count = 30
print("count2:",count)
inner2()
print("count3:",count)
inner()
print("count4:",count)
outer()
print("count5:", count)
代码解析:
-
首行定义全局count=0。
-
outer()方法中没有global与nonlocal,因此为outer下的局部变量,值为10。
-
Inner()方法中定义局部变量count,且定义为nonlocal,因此与outer下的count绑定为同一变量,且更改值为20。
-
Inner2()方法中定义局部变量count,且定义为nonlocal,因此与inter下的count绑定为同一变量,且更改值为30,因此 outer和inner和inner2中的count为同一个变量。
-
各个方法下的print都是打印的本方法下的局部变量,因此count1 = 20,count2=30,count3=30,count4=30,而count5=0(因为全局的count没有与局部的count产生交集)。
下图为变量更新流程图:
再看一个例子:
n = 0
def f():
def inner():
nonlocal n
n = 2
n = 1
print("n1=",n)
inner()
print("n2=",n)
if __name__ == '__main__':
f()
print("n3=",n)
代码解析:
这个案例乍一看 inner方法中的n之前在这之前没有定义啊,其实代码运行时,是先运行n=1,再运行inner方法的。这边要注意的是,如果把n=1这行去掉,程序就会报错,因为nonlocal定义的变量在方法外必须要有定义。
-
首先定义全部变量n=0。
-
方法f()中定义局部变量n=1,没有nonlocal或global,因此与外面的n没有关系,因此n1=1。
-
调用方法inner,方法中定义局部变量n,且为nonlocal,即与f方法中的n绑定为同一变量,因此修改了f中的变量n值为2,因此打印n2=2。
-
由于f中的n与外部的n没有关系,因此n3=0,为原来的值。
03 总结
通过以上几个例子,可以理解nonlocal与global的区别了吧,总结几点就是:
-
global可以用于任何地方,声明变量为全局变量;声明后再修改,则修改了全局变量的值。
-
nonlocal的作用范围仅在于所在子函数的上一层函数中拥有的局部变量,且非全局变量。
-
global可以不需要提前定义,而nonlocal必须要提前定义。
最后: 为了回馈铁杆粉丝们,我给大家整理了完整的软件测试视频学习教程,朋友们如果需要可以自行免费领取 【保证100%免费】
这些资料,对于【软件测试】的朋友来说应该是最全面最完整的备战仓库,这个仓库也陪伴上万个测试工程师们走过最艰难的路程,希望也能帮助到你!
软件测试面试文档
我们学习必然是为了找到高薪的工作,下面这些面试题是来自阿里、腾讯、字节等一线互联网大厂最新的面试资料,并且有字节大佬给出了权威的解答,刷完这一套面试资料相信大家都能找到满意的工作。
所有资料获取方式: