Python 中的全局变量并不像想象的那样全局
Source: Dev.to
在 1980 年代的编程语境中,“全局变量”往往让人联想到像 MBASIC 这样的语言。如今,以 MBASIC 为例已经比较困难,因为它已经很少被使用或了解。这里改用 GNU Bash——许多系统的默认 Shell 脚本语言——来说明传统意义上的全局变量是怎样的。(有些人可能会想到 Fortran II,但我并不熟悉它。)
Bash 示例
a.bash
#!/bin/bash
. ./b.bash
. ./c.bash
. ./d.bash
init
print_count
inc
print_count
b.bash
inc() {
counter=$((counter + 1))
}
c.bash
print_count() {
echo $counter
}
d.bash
init() {
counter=1
}
Python 示例
a.py
import c, b, d
d.init()
c.print_count()
b.inc()
c.print_count()
b.py
import d
def inc():
d.counter += 1
c.py
import d
def print_count():
print(d.counter)
d.py
def init():
global counter
counter = 1
关键区别
正如你所看到的,Bash 中的全局变量在所有文件之间是真正全局的。而在 Python 中,全局变量仅在其所在模块(即文件)内部全局。修改 Bash 中的全局变量不需要任何特殊语法,而在 Python 中,函数必须显式声明 global 才能修改模块级变量。
因此,虽然两者都被称为“全局变量”,Python 的全局变量的作用域仅限于模块。这意味着它们不会干扰其他模块中的变量,除非我们有意让它们这么做。对于每个模块只使用一个类的开发者来说,Python 的全局变量的行为更像是类变量。此外,Python 函数内部的变量赋值默认是局部的,只有在明确声明后才会修改全局状态,从而防止意外的全局状态更改。
简而言之,许多针对 Bash 或 MBASIC 等语言的传统全局变量警告在 Python 中已不再适用。因此,我们可能需要重新考虑基于过去经验而自动拒绝全局变量的做法,而是根据具体使用场景进行审慎评估。