![机器学习入门: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=1739305967-x28ztbkEyvMyCXQI8IkjXWPvBRHyRYtM-0-8dc9d2377e1068ef74b3b0486417cc1c)
一个变量可以显式地声明为全局变量,如下所示:
![038-03](https://epubservercos.yuewen.com/8036B4/21821545908478506/epubprivate/OEBPS/Images/038-03.jpg?sign=1739305967-OFYcvpIdHWC0NJzZDz2Pbye1XD05IjNK-0-b8642abb03a64fee70ab74ec14e8d1c1)
下面的代码块对照演示了局部变量和全局变量的不同表现:
![038-04](https://epubservercos.yuewen.com/8036B4/21821545908478506/epubprivate/OEBPS/Images/038-04.jpg?sign=1739305967-eb03BOvWehpE3sv0iPcX5IIp0h0qurna-0-58f9f6ebab5dcceec7a012249fb58ebc)
上述代码块的输出如下所示:
![038-05](https://epubservercos.yuewen.com/8036B4/21821545908478506/epubprivate/OEBPS/Images/038-05.jpg?sign=1739305967-eqMVgKtsLlFbAMLwaKUN2S7CuLidzXrc-0-2a145e317fcdacf78d9282d4a3b06cda)
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=1739305967-DEf0RHJR4mRN8Ydt5h93lWe4y97IKSsX-0-c5e0ae9c5f811a586e078cc2782ae91f)
假设file1.py
中包含如下代码:
![039-02](https://epubservercos.yuewen.com/8036B4/21821545908478506/epubprivate/OEBPS/Images/039-02.jpg?sign=1739305967-jYzVtPOx4qcrNADWibeAJSM9DVeVOnHy-0-db3ccd53aa21f1272e28bbe7437729d8)
在命令行中运行file1.py
,你会得到如下输出:
![039-03](https://epubservercos.yuewen.com/8036B4/21821545908478506/epubprivate/OEBPS/Images/039-03.jpg?sign=1739305967-RU7ykVHPlBqommbyaANu5m4nDKAy1Ydg-0-ad3cfec578f0bd8acf6c3361ce194788)
第二个场景涉及一段包含两个变量的程序,一个是局部变量,一个是全局变量,两个变量具有相同的命名。根据前面的规则,在定义变量的函数内使用的是局部变量,而在函数外会使用全局变量。
下面的代码说明了具有相同变量名的局部变量和全局变量的用法:
![039-04](https://epubservercos.yuewen.com/8036B4/21821545908478506/epubprivate/OEBPS/Images/039-04.jpg?sign=1739305967-S71UgsHf0NIG8L5wsKahO6ktwYMNN2Xn-0-ed12c44761efe8600bbb9fc3b4568653)
当执行上述代码的时候,将得到以下结果:
![039-05](https://epubservercos.yuewen.com/8036B4/21821545908478506/epubprivate/OEBPS/Images/039-05.jpg?sign=1739305967-T3z82ZzgJsZcypvhP78jyhLKMHWxddcx-0-2145ab7caf4516e0ae2ef2c9ab82d880)
对于不确定作用域的变量,在使用变量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=1739305967-3hnAXmYD9e93POT52lXjXKwsv7uxswFm-0-9990bc55ec3c6eb3a86520b6f5705ed9)
注意:你可以通过调用locals()
和globals()
来访问Python用于跟踪局部变量和全局变量的字典。
2.2.3 引用传递和值传递
Python中的所有参数(形参和实参)都是引用传递。因此,当你在一个函数内修改了其形参引用的时候,这个改变会反映在其调用函数中。例如:
![040-02](https://epubservercos.yuewen.com/8036B4/21821545908478506/epubprivate/OEBPS/Images/040-02.jpg?sign=1739305967-cGZEkx1zUAm6dsjQSIP5jX2gsgWhhMil-0-fa815a6adae92d486e244b4f1b257c8a)
这里我们持有对传递对象的引用,并对其添加值。它的结果如下所示:
![040-03](https://epubservercos.yuewen.com/8036B4/21821545908478506/epubprivate/OEBPS/Images/040-03.jpg?sign=1739305967-hZBZCrAd6J8uDDzkERw9CEK78Jb4TKuI-0-d6366ae4f48eed65dabc0943b3763826)
引用传递这一事实引出了可变性与不可变性的概念,我们将在第3章讨论。
2.2.4 实参和形参
Python区分函数调用时的实参和函数声明时的形参:位置(强约束)和关键字(可选/默认值)。这个概念很重要,因为Python有用于包装和拆包这类参数的运算符。
Python从迭代器中拆包位置参数,如下所示:
![041-01](https://epubservercos.yuewen.com/8036B4/21821545908478506/epubprivate/OEBPS/Images/041-01.jpg?sign=1739305967-LWa1HKX6fH6RTYRZ2zbwd9wXTPD8OjNO-0-d6fa790ff4bc6a5027ac97d6e4427057)