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