首页 » 与孩子一起学编程 » 与孩子一起学编程全文在线阅读

《与孩子一起学编程》13.6 变量作用域

关灯直达底部

你可能已经注意到,有些变量在函数之外,如 totalPrice,还有一些变量在函数内部,如 total。这些变量只是同一个东西的两个不同名字。这就像第 2 章中所说的 YourTeacher = MyTeacher

在我们的 calculateTax 例子中,totalPricetotal 是贴在同一个东西上的两个标签。对于函数而言,函数内的名字只是在函数运行时才会创建。在函 数运行之前或者完成运行之后甚至根本不存在。Python 提供了内存管理(memory management),可以自动完成这个工作。Python 在函数运行时会创建新的名字在函数内使用,当函数完成时会把它们删除。最后这部分很重要:函数运行结束时,其中的所有名字都不再存在。

函数运行时,函数之外的名字被搁置一边,而没有用到。只有函数内部的名字会被用到。程序中使用(或者可以使用)变量的部分称为这个变量的作用域(scope)。

局部变量

在代码清单 13-4 中,变量 pricetotal 只在函数内使用。我们说 pricetotaltax_rate 的作用域是 calculateTax 函数。这也称为这些变量是局部的(local)。pricetotaltax_rate 变量是 calculateTax 函数中的局部变量。

要了解这是什么意思,一种方法是向代码清单 13-4 中的程序增加一行代码,尝试在函数之外的某个位置打印 price 的值。代码清单 13-5 做了这个尝试。

代码清单 13-5 尝试打印一个局部变量

如果运行这个程序,会得到这样一个错误:

错误消息的最后一行解释了这个问题的原委:在 calculateTax 函数以外,变量 price 根本没有定义。它只是在函数运行时才存在。试图在这个函数之外打印 price 的值时(此时函数并没有运行),就会得到一个错误。

全局变量

与局部变量 price 对应,代码清单 13-5 中的变量 my_pricetotalPrice 在函数之外定义(程序主部分中)。我们使用全局变量(global)表示有更大作用域的变量。在这种情况下,更大是指程序的主部分,而不是函数内部。如果扩展代码清单 13-5 中的程序,完全可以在另一个位置使用变量 my_pricetotalPrice,它们仍然有之前给定的值。它们仍在合法的作用域中(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。