![机器学习入门:Python语言实现](https://wfqqreader-1252317822.image.myqcloud.com/cover/84/41787084/b_41787084.jpg)
2.2 Python中的变量和参数
2.2.1 局部变量和全局变量
Python中的变量可以是局部变量也可以是全局变量。变量在以下情况时,是一个函数的局部变量:
- 作为函数的形参。
- 出现在函数中声明语句的左边。
- 限定在控制结构内部(如
for
、with
和except
)。
当一个非局部的变量(在之前的代码中出现)在函数内被引用,那么它是一个非局部变量。你可以按如下所示指定一个非局部变量:
![038-02](https://epubservercos.yuewen.com/8036B4/21821545908478506/epubprivate/OEBPS/Images/038-02.jpg?sign=1739318110-sk120E3Ou40hvy4fYoLr97m0M1Tn8rpf-0-960dee14e46b0e5c0cabf2fcbcc9a9db)
一个变量可以显式地声明为全局变量,如下所示:
![038-03](https://epubservercos.yuewen.com/8036B4/21821545908478506/epubprivate/OEBPS/Images/038-03.jpg?sign=1739318110-Fhj52Ogo3r7zfu7chW0cXwBXPVaeOvQW-0-c64fff97d33bc753e4e11ea43b559cff)
下面的代码块对照演示了局部变量和全局变量的不同表现:
![038-04](https://epubservercos.yuewen.com/8036B4/21821545908478506/epubprivate/OEBPS/Images/038-04.jpg?sign=1739318110-O0Ld3ceHHKiRCco6yIVqHcbusbUGqc6l-0-923f82620d7c50dc9bdb4703711f38fd)
上述代码块的输出如下所示:
![038-05](https://epubservercos.yuewen.com/8036B4/21821545908478506/epubprivate/OEBPS/Images/038-05.jpg?sign=1739318110-HArycv1hhCDq6w1MNCZ77Acl0VpkzVlH-0-1d79dfc5fa7679a59ac31b1ca8e4463b)
2.2.2 变量的作用域
Python变量的可访问性或作用域取决于变量的定义位置。Python提供两种作用域:全局作用域和局部作用域。全局变量实际上是模块级别的作用域(即当前文件),因此你可以在不同的文件中使用相同的名称定义变量,它们会被当作不同的变量对待。
局部变量很简单:它们是在函数内定义的变量,并且只能在定义它们的函数内被访问。任何非局部的变量都具有全局作用域,这些变量只对定义它的文件是“全局的”,并且可以在文件中的任何地方访问它们。
下面看两个关于变量的场景。首先,假设有两个文件(即模块)file1.py
和file2.py
都包含一个叫作x
的变量,同时file1.py
导入了file2.py
。现在的问题是如何在这两个文件中区分变量x
。举个例子,假设file2.py
中包含下面两行代码:
![039-01](https://epubservercos.yuewen.com/8036B4/21821545908478506/epubprivate/OEBPS/Images/039-01.jpg?sign=1739318110-dB8NR1k7V7n3wnOXg4wT3ahpbosfgTcF-0-1313982e85b77b42a4c93cae0299a5c0)
假设file1.py
中包含如下代码:
![039-02](https://epubservercos.yuewen.com/8036B4/21821545908478506/epubprivate/OEBPS/Images/039-02.jpg?sign=1739318110-apCjNWPL1fSkZvBS6zC8H6fZIN6U6eIK-0-b3da69899651009d64a0f030a8f94c3f)
在命令行中运行file1.py
,你会得到如下输出:
![039-03](https://epubservercos.yuewen.com/8036B4/21821545908478506/epubprivate/OEBPS/Images/039-03.jpg?sign=1739318110-s7bYqkrpu9bmLeUlkd9abGqHXfyYJGhO-0-f5b3d2c0a3b969ce814388f6cdc7f5af)
第二个场景涉及一段包含两个变量的程序,一个是局部变量,一个是全局变量,两个变量具有相同的命名。根据前面的规则,在定义变量的函数内使用的是局部变量,而在函数外会使用全局变量。
下面的代码说明了具有相同变量名的局部变量和全局变量的用法:
![039-04](https://epubservercos.yuewen.com/8036B4/21821545908478506/epubprivate/OEBPS/Images/039-04.jpg?sign=1739318110-bw4B6zZKsnhrBs1VX9x4do3LGDWs9v3o-0-89628c9164359bff2b05c189bf6ae130)
当执行上述代码的时候,将得到以下结果:
![039-05](https://epubservercos.yuewen.com/8036B4/21821545908478506/epubprivate/OEBPS/Images/039-05.jpg?sign=1739318110-zCasOkmOsMj5ua3Y8ELg7b1OqtaGs9aR-0-561750c698111c9d6553a5a02a2392ad)
对于不确定作用域的变量,在使用变量x
时不带模块前缀会怎么样?答案取决于Python执行的以下一系列步骤:
1)在局部作用域中检查该名称的变量。
2)扩大检查的封闭作用域,并检查该名称的变量。
3)执行第2步直到检查全局作用域(即模块级别)。
4)如果仍未找到x
,则检查Python的__builtins__
(内建模块)。
![040-01](https://epubservercos.yuewen.com/8036B4/21821545908478506/epubprivate/OEBPS/Images/040-01.jpg?sign=1739318110-um2Uxa5xDyYbIIBvNd1T2dRNbgfbblJc-0-8916ab46e1c33f85e70b083017ec4794)
注意:你可以通过调用locals()
和globals()
来访问Python用于跟踪局部变量和全局变量的字典。
2.2.3 引用传递和值传递
Python中的所有参数(形参和实参)都是引用传递。因此,当你在一个函数内修改了其形参引用的时候,这个改变会反映在其调用函数中。例如:
![040-02](https://epubservercos.yuewen.com/8036B4/21821545908478506/epubprivate/OEBPS/Images/040-02.jpg?sign=1739318110-YcPs8cDRAGVCCmpfYPGIZxtWsUtA1TWk-0-1b35c37eb9a630e1a4a00ff09122b448)
这里我们持有对传递对象的引用,并对其添加值。它的结果如下所示:
![040-03](https://epubservercos.yuewen.com/8036B4/21821545908478506/epubprivate/OEBPS/Images/040-03.jpg?sign=1739318110-5FN3mjaREA2lh4OOUeu2dX2GO8GvZPRN-0-3661d8be6087f9a20d32f9bdaedf6007)
引用传递这一事实引出了可变性与不可变性的概念,我们将在第3章讨论。
2.2.4 实参和形参
Python区分函数调用时的实参和函数声明时的形参:位置(强约束)和关键字(可选/默认值)。这个概念很重要,因为Python有用于包装和拆包这类参数的运算符。
Python从迭代器中拆包位置参数,如下所示:
![041-01](https://epubservercos.yuewen.com/8036B4/21821545908478506/epubprivate/OEBPS/Images/041-01.jpg?sign=1739318110-MZ0Se6KsnNsFguLA3K7M2XX8RD10KaDB-0-6663f6df60d832d442c21a319a7f2e3a)