使用函数参数比使用全局变量更好的原因有以下几个:
- 它消除了可能的混淆:一旦您的程序变大,就很难跟踪在哪里使用了哪个全局变量。传递函数参数可以让您更清楚地了解函数使用哪些值。
- 如果你使用全局变量,你最终会犯一个特别的错误,在你理解发生了什么之前,这看起来很奇怪。它与修改和读取同一函数中的全局变量有关。稍后再谈。
- 全局变量都存在于同一个命名空间中,因此您很快就会遇到名称重叠的问题。如果你想要两个不同的名为“index”的变量怎么办?打电话给他们会变得非常混乱,非常快
index1
。index2
使用局部变量,或函数参数,意味着它们都存在于不同的命名空间中,混淆的可能性大大降低。
现在,我提到了在同一个函数中修改和读取全局变量,以及可能导致的令人困惑的错误。这是它的样子:
record_count = 0 # Global variable
def func():
print "Record count:", record_count
# Do something, maybe read a record from a database
record_count = record_count + 1 # Would normally use += 1 here, but it's easier to see what's happening with the "n = n + 1" syntax
这将失败:UnboundLocalError: local variable 'record_count' referenced before assignment
等等,什么?当它显然是全局变量时,为什么record_count
被视为局部变量?好吧,如果你从未在函数中赋值,record_count
那么 Python 将使用全局变量。但是当你给 赋值时record_count
,Python 不得不猜测你的意思:是要修改全局变量,还是要创建一个新的局部变量来隐藏(隐藏)全局变量,并且只处理局部变量多变的。Python 会默认假设你对全局变量很聪明(即,在不知道你在做什么和为什么的情况下不修改它们),并假设你打算创建一个名为record_count
.
但是,如果您要访问record_count
函数内部命名的局部变量,Python 将不允许您访问函数内部具有相同名称的全局变量。这是为了避免一些非常讨厌的、难以追踪的错误。这意味着如果这个函数有一个名为的局部变量record_count
——并且由于赋值语句而确实如此——那么所有访问都record_count
被认为是访问局部变量。包括语句中的访问print
,在定义局部变量的值之前。因此,UnboundLocalError
例外。
现在,给读者做一个练习。删除 print 语句并注意仍然抛出异常UnboundLocalError
。你能弄清楚为什么吗?(提示:在分配给变量之前,必须计算分配右侧的值。)
现在:如果你真的想record_count
在你的函数中使用全局变量,这样做的方法是使用 Python 的global
语句,它说“嘿,我要指定这个变量名?永远不要让它成为局部变量,即使我分配给它。而是分配给全局变量。” 它的工作方式只是global record_count
(或任何其他变量名),位于函数的开头。因此:
record_count = 0 # Global variable
def func():
global record_count
print "Record count:", record_count
# Do something, maybe read a record from a database
record_count = record_count + 1 # Again, you would normally use += 1 here
这将首先满足您的期望。但希望现在你明白为什么它会起作用,而另一个版本不会。