今天在运行python时遇到了局部变量和全局变量的问题,令我很迷惑。
首先,我在学习python之前先学习了c语言,所以c语言的一些东西影响了我对这个问题的思考。
在c语言中
局部变量和全局变量的区别就在于作用域的范围大小。在c语言中,我们认为定义在函数内部或循环体(for语句、while语句)和if语句内部的变量为局部变量,除此之外定义的变量称之为全局变量。
在if语句内部定义变量,在if语句外面输出
在上图中,我在if语句内部定义了一个n整数变量,在if语句外面输出,编辑器会给予我报警提示。
同理,换成函数或循环体是一样的。
在python中
我想这两种语言在这个方面应该保持一致吧?结果问题出现了。
同样的程序换成了python却出现了结果,答案为2。这是为何呢?
经过查阅资料,我发现网上很多都说不应该输出值,应该报错。
比如:Python Python if条件语句中的变量作用域|极客教程
上面显示在if外边输出会报错,但实际运行并不会。
所以我重新思考了一番:认为python的局部变量并不同于c语言。仅仅是在def(也就是函数)内部定义变量才是局部变量(当然不使用global关键字),在函数外部定义是全局变量。
像我在本节开头提到的那个程序,先在if内部定义了一个n,然后自加,接着在if外部输出,这种定义的统统按照全局变量处理。所以才会在结果中输出2。
同样,我也找到了一些相同看法的人。例如这位阿常呓语博主:python3中 for 循环中循环变量的作用域问题_python for循环变量作用域-CSDN博客
在python中,当你在函数外部定义变量时,认为是同一级别的作用域,统一按照全局变量处理。
重新审视python的全局变量与局部变量
在得到上述结论后,来重新审视一下全局变量和局部变量。这里引用了上文提到的阿常呓语博主的文章中的一些例子。
例子一
num = 10000000
print(f"module num:{num}")
def visit_num():
print(f"visit num:{num}")
if __name__ == '__main__':
visit_num()
print(f"main num:{num}")
结果:
module num:10000000
visit num:10000000
main num:10000000
解释:全局变量的作用范围是整个文件。所以输出都是一样的。
例子二
num = 10000000
print(f"module num:{num}")
def visit_num():
num = 0
print(f"visit num:{num}")
if __name__ == '__main__':
visit_num()
print(f"main num:{num}")
结果:
module num:10000000
visit num:0
main num:10000000
解释:首先定义的num是在函数外部,所以是全局变量。然后定义了visit_num函数,内部定义了相同的变量num为0。最后调用函数,输出num。
这里要注意:只要是在函数内部定义的变量统统认为是局部变量。(除了global声明,例子四提到)所以内部定义的num虽然和外部的变量同名,但是两者并不是一回事。所以visit num为0,调用结束后局部变量就结束了它的生命。此时只有一个num变量,就是全局的num。所以最后的main num为10000000
例子三
如果我将例子二中函数内部的num=0和print(f"visit num:{num}")两行交换顺序会怎样呢?
num = 10000000
print(f"module num:{num}")
def visit_num():
print(f"visit num:{num}")
num=0
if __name__ == '__main__':
visit_num()
print(f"main num:{num}")
结果:报错
解释:在例子二中已经说过,只要是在函数内部定义的变量都是局部变量。所以调用visit_num函数时系统会首先检查这个函数中有没有定义num变量(这个检索是整个函数范围的,而不仅仅是此行之前的),如果没有那就输出全局的num变量,如果有就输出局部的num变量。显然,这个函数内部声明了局部的num变量了,但是在print语句之前我并不知道num变量是多少,所以会报错。换句话说,就是num“事后诸葛亮“了。
所以从这里可以得出一个结论,如果要声明局部变量,必须在函数开头(至少在输出之前,“开始检索”之前)就声明,否则就会报错。
例子四
在函数内部修改全局变量。
前面我们说过,函数内部定义的变量均为局部变量,但是有一个例外。如果函数内部使用了global关键字,那么这时修改的变量就是全局变量了。
num = 10000000
print(f"module num:{num}")
def visit_num():
global num
num=0
print(f"visit num:{num}")
if __name__ == '__main__':
visit_num()
print(f"main num:{num}")
结果:
module num:10000000
visit num:0
main num:0
额外:也有人说列表中的循环变量是一个例外情况,其实不然。下面的这个问答可以解决此问题,
python的for循环变量为何不设置为局部变量?_编程语言-CSDN问答
a = 1
b = [1,2,3,4,5]
for a in b:
c = 0
print(a)
这个其实在开始就说过了,python的全局变量和c不同。
分析这个代码:首先a为全局变量赋值为1,for a in b的理解是将b中的每一个值依次赋值给a,所以相当于每次赋值都修改了a这个全局变量,所以最后输出的a值为5.
个人理解,如有错误,还请不吝赐教。