机器学习入门:Python语言实现
上QQ阅读APP看书,第一时间看更新

2.2 Python中的变量和参数

2.2.1 局部变量和全局变量

Python中的变量可以是局部变量也可以是全局变量。变量在以下情况时,是一个函数的局部变量:

  • 作为函数的形参。
  • 出现在函数中声明语句的左边。
  • 限定在控制结构内部(如forwithexcept)。

当一个非局部的变量(在之前的代码中出现)在函数内被引用,那么它是一个非局部变量。你可以按如下所示指定一个非局部变量:

038-02

一个变量可以显式地声明为全局变量,如下所示:

038-03

下面的代码块对照演示了局部变量和全局变量的不同表现:

038-04

上述代码块的输出如下所示:

038-05

2.2.2 变量的作用域

Python变量的可访问性或作用域取决于变量的定义位置。Python提供两种作用域:全局作用域和局部作用域。全局变量实际上是模块级别的作用域(即当前文件),因此你可以在不同的文件中使用相同的名称定义变量,它们会被当作不同的变量对待。

局部变量很简单:它们是在函数内定义的变量,并且只能在定义它们的函数内被访问。任何非局部的变量都具有全局作用域,这些变量对定义它的文件是“全局的”,并且可以在文件中的任何地方访问它们。

下面看两个关于变量的场景。首先,假设有两个文件(即模块)file1.pyfile2.py都包含一个叫作x的变量,同时file1.py导入了file2.py。现在的问题是如何在这两个文件中区分变量x。举个例子,假设file2.py中包含下面两行代码:

039-01

假设file1.py中包含如下代码:

039-02

在命令行中运行file1.py,你会得到如下输出:

039-03

第二个场景涉及一段包含两个变量的程序,一个是局部变量,一个是全局变量,两个变量具有相同的命名。根据前面的规则,在定义变量的函数内使用的是局部变量,而在函数外会使用全局变量。

下面的代码说明了具有相同变量名的局部变量和全局变量的用法:

039-04

当执行上述代码的时候,将得到以下结果:

039-05

对于不确定作用域的变量,在使用变量x时不带模块前缀会怎么样?答案取决于Python执行的以下一系列步骤:

1)在局部作用域中检查该名称的变量。

2)扩大检查的封闭作用域,并检查该名称的变量。

3)执行第2步直到检查全局作用域(即模块级别)。

4)如果仍未找到x,则检查Python的__builtins__(内建模块)。

040-01

注意:你可以通过调用locals()globals()来访问Python用于跟踪局部变量和全局变量的字典。

2.2.3 引用传递和值传递

Python中的所有参数(形参和实参)都是引用传递。因此,当你在一个函数内修改了其形参引用的时候,这个改变会反映在其调用函数中。例如:

040-02

这里我们持有对传递对象的引用,并对其添加值。它的结果如下所示:

040-03

引用传递这一事实引出了可变性与不可变性的概念,我们将在第3章讨论。

2.2.4 实参和形参

Python区分函数调用时的实参和函数声明时的形参:位置(强约束)和关键字(可选/默认值)。这个概念很重要,因为Python有用于包装和拆包这类参数的运算符。

Python从迭代器中拆包位置参数,如下所示:

041-01