4.2.5 变量的作用域

程序中的变量都有自己的作用域(scope,或称辖域),即程序的一部分区域,在其中可以访问该变量。一个变量只有在它的作用域中才有定义,才能被访问。

局部变量

在一个函数中定义的变量称为局部变量(local variable),因为它们的作用域局限于该 函数的函数体,在函数外部是没有定义的。例如:

>>> def func(x,y):
        z = x + y print z
>>> func(1,2)
3

函数 func 中定义了局部变量 z。由于语句 print z 是 func 函数体内的语句,所以 可以访问 z。如果函数外部的 print 语句试图显示 z 的值,则会出错。例如接着上例继续 执行:

>>> print z
Traceback (most recent call last):
File "<pyshell#9>", line 1, in <module> print z
NameError: name 'z' is not defined

函数的形式参数也可以看作是函数的局部变量,即只能在函数体内访问。形式参数不同 于局部变量的是:形式参数的值是在调用函数时通过参数传递而来的。如上例中函数 func 有两个参数 x 和 y,当调用 func(1,2)时相当于执行了两个对局部变量的赋值语句 x = 1 和 y = 2。

函数的局部变量和形式参数仅在函数体内有定义,因此即使与函数外部的变量同名也不 会带来问题。例如我们接着上例继续执行语句:

>>> x = 1
>>> z = 2
>>> func(x,z)
3

这里,x 和 z 是在函数 func 的外部定义的变量,它们虽然分别与 func 的形式参数 x 和局 部变量 z 同名,但实际上毫无联系。执行 func(x,z)时,Python 先在 func 外部计算 x 和 z 的值,然后将结果传递给 func 的形式参数 x、y,因此最终执行的是 func(1,2)。图 4.6 给出了这个过程的示意图。

图 4.6 函数局部变量与外部变量同名 全局变量

函数内部的变量具有局部性,这符合模块化编程思想的要求。作为一种模块化构件,函 数就像“黑盒”一样,其内部细节应该对外部不可见。同理,函数内部也不应直接使用外界 的东西。如果函数需要外界的数据,正确的做法是通过参数来传递给函数。也就是说,函数 的参数除了用于表示可变数据、增强函数的通用性之外,还应作为外界向函数传递数据(即使是一个固定不变的数据)的唯一渠道。下面是一个函数直接使用外界数据的例子:

>>> s = "hello"
>>> def f():
        print s
>>> f()
hello

这里,函数 f()的功能是打印变量 s 的值,但这个 s 并不是 f()自己的局部变量,而是 f() 外部的变量,相对于 f()可称为全局变量(global variable)。尽管这个用法在 Python 中是合 法的,但这不是好的编程风格。正确的做法是将变量 s 的值通过参数传递给 f():

>>> s = "hello"
>>> def f(x):
        print x
>>> f(s)
hello

在实际应用中,可能会有多个函数共同操作(读取或修改)一个数据的情形,这时采用 参数传递的方式比较麻烦,而采用全局变量则显得直接了当。下面我们用一个简单程序说明 Python 中全局变量的用法。

【程序 4.7】eg4_7.py

def f():
    global x 
    x = x + 1 
    print x
def g():
    global x 
    x = x - 1 
    print x
    x = 0 
f()
g()

程序中定义了两个函数 f()和 g(),它们的函数体中都包含一条声明全局变量的语句: global x 意为本函数中所使用的 x 是在函数外部定义的全局变量。f()的功能是对全局变量 x 加 1,g()的功能是对全局变量 x 减 1。执行结果如下:

>>> import eg4_1
1
0

可见执行 f()之后 x 变成了 1,再执行 g()又把 x 改回了 0。