4.13 作用域规则

标识符在程序中可以使用的区域称为标识符的作用域。当标识符在这一区域内使用时,称为“在作用域内”。

局部作用域

局部变量的标识符具有局部作用域。从局部变量在函数块中的定义开始到函数块的结尾属于“作用域内”。当函数返回时,局部变量将“超出作用域”。因此,局部变量只能在定义它的函数内使用。

全局作用域

在任何函数(或类)之外定义的标识符具有全局作用域,这些标识符可以是函数名、变量名和类名。具有全局作用域的变量称为全局变量。在.py文件或交互式会话中定义了具有全局作用域的标识符后,可以在定义该标识符之后的任何位置使用它。

在函数中访问全局变量

可以在函数中访问全局变量的值:

但是,在默认情况下,无法在函数中修改全局变量。当在函数块中为全局变量赋值时,Python会创建一个与该全局变量同名的局部变量,如下:

在函数try_to_modify_global的块中,局部变量x屏蔽了全局变量x,使其在函数块的范围内不可访问。代码段[6]显示全局变量x仍然存在,并且在函数try_to_modify_global执行后保持其原始值(7)不变。

要在函数块中修改全局变量的值,必须使用global语句声明变量是在全局作用域定义的,例如:

块与套件

如果定义了函数和控制语句套件,在函数块中创建变量时,它是该块的局部变量;但是,在控制语句的套件中创建变量时,变量的作用域取决于控制语句定义的位置,规则如下:

  • 如果控制语句位于全局作用域,则任何在控制语句中定义的变量都具有全局作用域;
  • 如果控制语句位于函数块中,则任何在控制语句中定义的变量都具有局部作用域。

我们会在第10章中介绍自定义类时,对作用域做进一步的讨论。

屏蔽函数

在前面的章节中,当需要对多个值进行求和时,会将总和存储在名为total的变量中,而不使用sum作为变量名,这样做是因为sum是一个内置函数的函数名。如果定义一个名为sum的变量,它会将内置函数sum屏蔽,使其无法在代码中访问。例如,在下面的代码中为变量sum赋值时,Python会将标识符sum绑定到int对象,而不再引用内置函数sum。因此,当尝试将sum用作函数名时,会引发TypeError

全局作用域的语句

到目前为止,在我们编写过的脚本中,程序语句既有处在函数外部全局作用域的,也有处在函数块内的。当解释器遇到脚本中处于全局作用域的语句时会立即执行,而处于函数块内的语句则仅在调用该函数时才会执行。