作用域代表着一个影响范围,作用域可以理解为变量的有效范围
有了函数的定义,代码结构会逐渐变得复杂起来,此时经常遇到的一个问题就是变量名称的冲突问题。我们不妨从一个例子开始:
def func(num):
num = 2
print(num)
num = 1
func(num)
print(num)
输出为:
2
1
大家能看出输出结果为什么是这个吗?
这里面虽然出现了很多个num变量(这里是为了练习,其实这种写法并不可取),但是它们并非是一个变量。我们按照代码的执行次序来仔细看看这些变量的变化。
1)首先是函数func的定义。对于定义部分,我们可以先不看,函数只有在被调用执行的时候,才真正被运行;
2)定义了一个num变量,初始值为1;
3)开始调用func函数,这个过程涉及到两个变量,一个是写在调用函数括号内的num,用于将数值传递给函数内部的参数,这个变量是实参;第二个是定义在函数里的参数num,用于接收传递过来的数值,这个变量是形参。虽然此时实参和形参两个变量名称一样,但是并不是一个变量;
4)接下来开始执行函数func,该函数修改了num的数值,变成了2,但此时只是形参发生了改变。
函数继续执行,输出也是形参的数值,为2。然后,函数运行结束。但是函数外部的实参num并没有改变;
5)函数结束运行后,所有函数内部的变量都会被销毁。因此,那个数值为2的形参num已经不复存在,退一步说,即使存在,在函数func外部,也无法访问函数内部的变量。
因此,此时再次输出的num其实是实参num的数值,它依然为1。
如果我们想在函数中访问到函数外的变量,甚至去改变它,这也是可行的。具体的方法是使用global语句:
def func():
global num
num = 2
print(num)
num = 1
func()
print(num)
输出为:
2
2
显然函数外面的num被函数改变了。此时该如何理解呢?其实也很简单,那就是在func中的num前面有个global语句声明,这就说明这个num不是自己的num,而是全局的num,global就是全局的意思。所谓全局就是整个代码区域,所以此时它会自动去在全局范围内去寻找num变量,找到后就直接使用这个变量,既可以读,也可以写,所以func函数才能改变外部的num变量数值。
进一步说,如果全局没有这个num变量的话,它也会新建一个,并且在函数结束运行后依然保持存在。
def func():
global num
num = 2
print(num)
func()
print(num)
输出内容同上。
不过,global变量还是慎用为上,事实上,良好的代码结构和稳定的代码内容往往还是依赖于低耦合,就是不建议大家广泛的使用这种跨域的数据访问,避免潜在而且非常难以排查的错误。乱用全局变量的代码,有人形象的比喻为一团意大利面条:)
配套学习资源、慕课视频: