五、变量名的查找顺序

上面说过,Python中的变量有四种作用域,那么当函数引用一个变量时,它是以怎样的顺序在这些作用域中查找变量呢?下面我们将详细说明。

当某个函数引用一个变量时,比如变量x,它首先在该函数的局部作用域中查找该变量,如果在局部作用域中有对该变量的赋值语句,并且没有用关键词global,即没有将其声明为全局变量,如下所示:

x = 6

这相当于在该函数内部定义了一个局部变量,那么这个名为x值为6的整型变量就是我们要找的。如果在当前函数的局部作用域中没有找到该变量的定义,并且当前函数是某个函数的内部函数的话,那么继续由内向外在所有外部函数中查找该变量的定义,并且将最先找到的赋值语句作为它的定义,并将第一个赋给它的值作为我们要找的变量的值。如果在所有外部函数中都没有找到该变量的定义,或者根本就没有外部函数,那么继续在全局作用域中查找。如果在全局作用域中还没有找到x的定义,那么就到Python内建的作用域去找,如果四个作用域都没找到的话,则说明引用了一个未加定义的变量,这时Python解释器就会报错。

读者可以对照图4进行理解。

下面我们以示例代码进行讲解,代码如下所示:

def f():
x = 0
def f1():
x = 1
def f2():
x = 2
def f3():
x = 3
print '目前在函数f3)中,变量x的值为:',x
print '目前在函数f2)中,变量x的值为:',x
f3()
print '目前在函数f1)中,变量x的值为:',x
f2()
print '目前在函数f)中,变量x的值为:',x
f1()

上述代码中出现了多层嵌套的函数,其中函数f3)嵌套在函数f2)中,函数f2)嵌套在函数f1)中,函数f1)嵌套在函数f)中。但是,每个函数中都对变量x进行了定义,所以各个函数都能在其局部定义域中找到变量x。上述代码在交互式环境下的执行结果如下所示:


图7  在局部作用域中找到变量x的情形

在函数f)中,变量x被赋值为0,根据查找变量时先从当前函数的局部作用域下手的规则,函数f)看到的变量x的值就是0,其它函数依此类推。

现在我们对上述代码稍作修改,将函数f3)和函数f2)中对变量x的定义去掉,看一下在当前函数中找不到变量的定义时的情形,代码如下所示:

def f():
x = 0
def f1():
x = 1
def f2():
def f3():
print '目前在函数f3)中,变量x的值为:',x
print '目前在函数f2)中,变量x的值为:',x
f3()
print '目前在函数f1)中,变量x的值为:',x
f2()
print '目前在函数f)中,变量x的值为:',x
f1()

上述修改后的代码在交互环境下执行情况如下所示:


图8   在局部作用域中找不到变量x的情形

从图8可以看出,在函数f3)、f2)、f1)中,变量的值都为1;只有在f0)中变量的值为0。对于函数f3)来说,当它打印变量x的值时,首先在其局部作用域中寻找变量x的定义,因为没有找到,所以继续向外到其外部函数f2)中寻找,结果在函数f2)的局部变量中也没有找到变量x的定义,所以又向函数f2)的外部函数即函数f1)中寻找,这次找到了变量x的定义,即

x = 1


评论关闭