在 Python 中,变数的范围会影响到它在程式中的可见性以及生命周期。主要分为两大类:区域变数 (local variable) 和全域变数 (global variable)。但在开始说明前,先来说明什么是Python 的作用域 (Scope)
什么是作用域?
在 Python 中,作用域指的是一个变数名称有效的范围。简单来说,就是一个变数在程式码中的哪些地方可以被存取。
Python 的作用域类型
Python 的作用域主要分为以下几种:
- Local 作用域: 函数内定义的变数,只在函数内有效。
- Enclosing 作用域: 包含非局部(non-local)且非全域的变数,通常在嵌套函数中出现。
- Global 作用域: 模组层级的变数,在整个模组中都有效。
- Built-in 作用域: 包含 Python 内建的函数和名称,例如 print()、len() 等。
作用域的查找顺序
Python 在查找变数时,会按照以下顺序搜寻:
x = "global" # 全局变数
def outer():
y = "enclosing" # 包含作用域变数
def inner():
z = "local" # 局部变数
print(x, y, z) # 输出:global enclosing local
inner()
outer()
在上面的例子中:
- x 是全局变数,可以在任何地方访问。
- y 是包含作用域变数,只能在 outer 函数和 inner 函数中访问。
- z 是局部变数,只能在 inner 函数中访问。
区域变数 (local variable)
定义: 在函数内部定义的变数称为区域变数。作用域: 仅在定义它的函数内有效。生命周期: 当函数执行完毕,区域变数就会被销毁。
def my_function():
x = 10 # x 是区域变数
print(x)
my_function()
# 在函数外部尝试访问 x 会报错,因为 x 只在 my_function 内有效
全域变数 (global variable)
定义: 在函数外部定义的变数称为全域变数。作用域: 在整个程式中都有效,包括在函数内。生命周期: 从定义开始,直到程式结束。
x = 20 # x 是全域变数
def my_function():
print(x) # 在函数内可以直接访问全域变数
my_function()
print(x)
x = 10 # 全域变数
def my_function():
y = 20 # 区域变数
print(x) # 可以访问全域变数
print(y) # 只能在函数内访问
my_function()
print(x) # 可以访问全域变数
print(y) # 会报错,因为 y 是区域变数,在函数外部无法访问
在函数内修改全域变数:global 关键字
为什么需要global关键字?一般来说,在函数内部,我们无法直接修改函数外部定义的全域变数。这是因为函数内部会创建一个新的命名空间,区域变数会优先于全域变数。
然而,如果我们确实需要在函数内修改全域变数,就必须使用global关键字来明确告诉 Python 解释器,我们要操作的是全域变数,而不是创建一个新的区域变数。
在函数内修改全域变数:直接修改会产生一个新的区域变数,并不会改变全域变数的值。要修改全域变数,需要使用global 关键字。
globe_x = 10
def change_global():
global globe_x
globe_x = 20
change_global()
print(globe_x) # 输出 20
命名冲突: 如果区域变数和全域变数名称相同,在函数内部会优先使用区域变数。
何时使用哪一种?
- 区域变数:大部分情况下,应该优先使用区域变数,因为它们有助于将变数的作用范围限制在函数内,避免命名冲突,提高程式码的可读性。
- 全域变数:某些情况下,需要在多个函数中共享数据,可以使用全域变数。但过多的全域变数会使程式码变得复杂,难以维护,因此应该谨慎使用。
小结
区域变数和全域变数是 Python 中非常重要的概念。理解它们的作用范围和生命周期,有助于写出更清晰、更易于维护的程式码。在一般情况下,应该优先使用区域变数,并尽量避免过多地使用全域变数。
- 建议:尽量避免使用 global 关键字尽量避免使用过多全域变数,因为这会增加程式码的耦合性,使得程式难以测试和维护。如果需要在多个函数中共享数据,可以考虑使用类或模组来管理这些数据。在函数内部修改全域变数时,一定要谨慎,因为这可能会导致意想不到的副作用。
使用 global 关键字会直接操作全域变数,修改后的结果会反映在程式的所有部分。
- 替代方案: 如果需要在函数之间共享数据,可以考虑使用类、模组或函数的返回值来传递数据,而不是直接修改全域变数。