你可能已经注意到,有些变量在函数之外,如 totalPrice,还有一些变量在函数内部,如 total。这些变量只是同一个东西的两个不同名字。这就像第 2 章中所说的 YourTeacher = MyTeacher。
在我们的 calculateTax 例子中,totalPrice 和 total 是贴在同一个东西上的两个标签。对于函数而言,函数内的名字只是在函数运行时才会创建。在函 数运行之前或者完成运行之后甚至根本不存在。Python 提供了内存管理(memory management),可以自动完成这个工作。Python 在函数运行时会创建新的名字在函数内使用,当函数完成时会把它们删除。最后这部分很重要:函数运行结束时,其中的所有名字都不再存在。
函数运行时,函数之外的名字被搁置一边,而没有用到。只有函数内部的名字会被用到。程序中使用(或者可以使用)变量的部分称为这个变量的作用域(scope)。
局部变量
在代码清单 13-4 中,变量 price 和 total 只在函数内使用。我们说 price、 total 和 tax_rate 的作用域是 calculateTax 函数。这也称为这些变量是局部的(local)。price、total 和 tax_rate 变量是 calculateTax 函数中的局部变量。
要了解这是什么意思,一种方法是向代码清单 13-4 中的程序增加一行代码,尝试在函数之外的某个位置打印 price 的值。代码清单 13-5 做了这个尝试。
代码清单 13-5 尝试打印一个局部变量
如果运行这个程序,会得到这样一个错误:
错误消息的最后一行解释了这个问题的原委:在 calculateTax 函数以外,变量 price 根本没有定义。它只是在函数运行时才存在。试图在这个函数之外打印 price 的值时(此时函数并没有运行),就会得到一个错误。
全局变量
与局部变量 price 对应,代码清单 13-5 中的变量 my_price 和 totalPrice 在函数之外定义(程序主部分中)。我们使用全局变量(global)表示有更大作用域的变量。在这种情况下,更大是指程序的主部分,而不是函数内部。如果扩展代码清单 13-5 中的程序,完全可以在另一个位置使用变量 my_price 和 totalPrice,它们仍然有之前给定的值。它们仍在合法的作用域中(in scope)。因为我们可以在程序的任何地方使用这些变量,所以把它们称作全局变量(global variable)。
在代码清单 13-5 中,试图在函数之外打印一个函数内的变量时,会得到一条错误消息。这个变量不存在,也就是说它在作用域之外(out of scope)。如果反过来:从函数内打印一个全局变量,你认为会发生什么?
代码清单 13-6 试图从 calculateTax 函数中打印变量 my_price。试试看会发生什么。
代码清单 13-6 在函数中使用全局变量
可以吗?真的可以!不过为什么呢?
开始讨论变量作用域时,我曾经说过,Python 利用内存管理在函数运行时自动创建局部变量。内存管理还会做其他事情。如果在函数中使用主程序中定义的变量名,Python 允许你使用这个全局变量,只要你不要试图改变它。
所以你可以这样做:
print my_price
或者这样做:
your_price = my_price
因为它们都不会改变 my_price。
如果函数的任何部分试图改变这个变量,Python 会创建一个新的局部变量。所以如果你打算这样做:
my_price = my_price + 10
那么 my_price 将是 Python 在函数运行时创建的一个新的局部变量。
在代码清单 13-6 的例子中,打印出的值是全局变量 my_price,因为函数没有改变这个变量。代码清单 13-7 中的程序表明,如果确实试图在函数内部改变全局变量,你会得到一个新的局部变量。试着运行这个程序,看看会有什么结果。
代码清单 13-7 尝试在函数内部修改一个全局变量
如果运行代码清单 13-7 中的代码,会有下面的输出:
可以看到,现在有两个名为 my_price 的不同变量,分别有不同的值。一个是 calculateTax 函数中的局部变量,我们将它设置为 10 000。另一个是主程序中定义的全局变量,用来获取用户的输入,它的值是 7.99。