通常来说,一段程序代码中所用到的名字(变量名、函数名等)并不总是有效或可用的,而限定这个名字的可用性的代码范围就是这个名字的作用域(scope)。
Python 中,源代码中变量名被赋值的位置决定了这个变量名的作用域。在被调用函数内赋值的变量,处于该函数的局部作用域;在所有函数之外赋值的变量,属于全局作用域。处于局部作用域的变量,被称为该函数的局部变量;处于全局作用域的变量,被称为该源文件的全局变量;函数可能有多层(函数内又定义函数),如果一个变量在一个外层的函数中定义,对于内层的函数来说,它是非局部变量。
关于作用域,有如下规则:
- 全局作用域中的代码不能使用任何局部变量;
- 局部作用域可以访问全局变量;
- 一个函数的局部作用域中的代码,不能使用其他局部作用域中的变量;
- 在不同的作用域中,可以使用相同的名字命名不同的变量;
- 当存在同名但不同作用域类型变量时,其优先访问顺序为:局部变量 > 非局部变量 > 全局变量 > 内置对象(builtins 模块导入的内置标识符);
- 使用
global和nonlocal语句声明的名称可将赋值的变量名分别映射到外围的模块和函数的作用域。
全局变量和局部变量的区别:
name = '张三' # name 为全局变量
def welcome():
name = '李四' # name 为局部变量,它遮蔽了全局变量 name
print(f'您好,{name}!') # 此处
welcome() # 您好,李四!
print(f'您好,{name}!') # 您好,张三!
# 上句中 name 为全局变量,此处函数内的局部变量 name 已超出作用域
在局部作用域中通过 global 语句声明全局变量:
name = '张三' # name 为全局变量
def welcome():
global name # 在局部作用域中通过 global 声明全局变量
name = '李四' # name 为全局变量,它遮蔽了前面的全局变量 name
print(f'您好,{name}!') # 此处
welcome() # 您好,李四!
print(f'您好,{name}!') # 您好,李四!
在实际开发中,建议:
- 尽量减少使用全局变量,函数应该依赖形参和返回值而不是全局变量;
- 尽量不要使全局变量和局部变量重名,以免造成代码混乱;
- 尽量避免跨文件(模块)直接修改另一个文件的变量。