>>> from env_helper import info; info()
页面更新时间: 2022-12-28 09:43:28
运行环境:
    Linux发行版本: Debian GNU/Linux 11 (bullseye)
    操作系统内核: Linux-5.10.0-20-amd64-x86_64-with-glibc2.31
    Python版本: 3.9.2

3.4. 变量作用域

在被调用函数内赋值的变量,处于该函数的“局部作用域”。 在所有函数之外赋值的变量,属于“全局作用域”。 处于局部作用域的变量,被称为“局部 变量”。处于全局作用域的变量,被称为“全局变量”。 一个变量必是其中一种,不能既是局部的又是全局的。

不止一次地看到人们在抱怨,全局变量是罪恶之源,根本就不应该使用它们。但是我不认为这个结论是显而易见正确的。我希望能听到一次有关全局变量的严肃认真的讨论。论坛中的朋友们很多都提到了他们都正在编程中使用全局变量。

先从全局变量的优点谈起。一般来说,全局变量是公认的在各个VI之间传递数据的有效方法,比起其它方式的全局变量(个人意见)更容易管理,因为假如我们使用了一个簇作为全局数据,我们没有办法确定在何处使用了它们,可能需要自己创建一个文件记录它们使用的位置。 但是全局变量则不然,通过全局变量的右键快捷菜单,我们可以很容找到引用全局变量的位置。

使用全局变量有两个不利之处,其一,引用全局变量需要创建数据的拷贝,这可能会导致潜在的竞争条件或者导致数据的丢失。其二,使用全局变量会中断数据流程。

————————————————

版权声明:本文为CSDN博主「iteye_17172」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。

原文链接:https://blog.csdn.net/iteye_17172/article/details/82294178

可以将“作用域”看成是变量的容器。当作用域被销毁时, 所有保存在该作用域内的变量的值就被丢弃了。只有一个全局作用域, 它是在程序开始时创建的。如果程序终止,全局作用域就被销毁, 它的所有变量就被丢弃了。否则,下次你运行程序的时候, 这些变量就会记住它们上次运行时的值。

一个函数被调用时,就创建了一个局部作用域。 在这个函数内赋值的所有变量,存在于该局部作用域内。 该函数返回时,这个局部作用域就被销毁了, 这些变量就丢失了。下次调用这个函数, 局部变量不会记得该函数上次被调用时它们保存的值。 作用域很重要,理由如下:

  • 全局作用域中的代码不能使用任何局部变量;

  • 但是,局部作用域可以访问全局变量;

  • 一个函数的局部作用域中的代码,不能使用其他局部作用域中的变量。

  • 如果在不同的作用域中,你可以用相同的名字命名不同的变量。也就是说,可以有一个名为 spam 的局部变量,和一名为 spam 的全局变量。

Python 有不同的作用域,而不是让所有东西都成全局变量,这是有理由的。 这样一来,当特定函数调用中的代码修改变量时, 该函数与程序其他部分的交互,只能通过它的参数和返回值。 这缩小了可能导致缺陷的代码作用域。如果程序只包含全局变量, 又有一个变量赋值错误的缺陷,那就很难追踪这个赋值错误发生的位置。 它可能在程序的任何地方赋值,而你的程序可能有几百到几千行! 但如果缺陷是因为局部变量错误赋值,你就会知道, 只有那一个函数中的代码可能产生赋值错误。

虽然在小程序中使用全局变量没有太大问题,但当程序变得越来越大时,依赖 全局变量就是一个坏习惯。

3.4.1. 局部变量不能在全局作用域内使用

考虑下面的程序,它在运行时会产生错误:

>>> def spam():
>>>     eggs = 31337
>>> spam()
>>> print(eggs)
---------------------------------------------------------------------------

NameError                                 Traceback (most recent call last)

<ipython-input-2-a6266361b70e> in <module>
      2     eggs = 31337
      3 spam()
----> 4 print(eggs)


NameError: name 'eggs' is not defined

发生错误是因为, eggs 变量只属于 spam() 调用所创建的局部作用域。 在程序执行从 spam 返回后,该局部作用域就被销毁了,不再有名为 eggs 的变量。 所以当程序试图执行 print(eggs) ,Python 就报错,说 eggs 没有定义。 你想想看,这是有意义的。 当程序执行在全局作用域中时,不存在局部作用域,所以不会有任何局部变量。 这就是为什么只有全局变量能用于全局作用域。

3.4.2. 局部作用域不能使用其他局部作用域内的变量

一个函数被调用时,就创建了一个新的局部作用域, 这包括一个函数被另一个函数调用时的情况。请看以下代码:

>>> def spam():
>>>     eggs = 99
>>>     bacon()
>>>     print(eggs)
>>> def bacon():
>>>     ham = 101
>>>     eggs =0
>>>
>>> spam()
99

在程序开始运行时, spam() 函数被调用, 创建了一个局部作用域。局部变量 eggs 被赋值为 99 。 然后 bacon() 函数被调用,创建了第二个局部作用域。 多个局部作用域能同时存在。在这个新的局部作用域中, 局部变量 ham 被赋值为 101 。局部变量 eggs (与 spam() 的局部作用域中的那个变量不同)也被创建,并赋值为0。

bacon() 返回时,这次调用的局部作用域被销毁。 程序执行在 spam() 函数中继续,打印出 eggs 的值。 因为 spam() 调用的局部作用域仍然存在, eggs 变量被赋值为 99 。这就是程序的打印输出。

要点在于,一个函数中的局部变量完全与其他 函数中的局部变量分隔开来。

3.4.3. 全局变量可以在局部作用域中读取

请看以下程序:

>>> def spam():
>>>     print(eggs)
>>> eggs = 42
>>> spam()
>>> print(eggs)
42
42

因为在 spam() 函数中,没有变元名为 eggs ,也没有代码为 eggs 赋值,所以当 spam() 中使用 eggs 时, Python 认为它是对全局变量 eggs 的引用。这就是前面的程 序运行时打印出42的原因。

3.4.4. 名称相同的局部变量和全局变量

要想生活简单,就要避免局部变量与全局变量或其他局部变量同名。但在技术 上,在 Python 中让局部变量和全局变量同名是完全合法的。为了看看实际发生的情 况,请在文件编辑器中输入以下代码,并保存为 sameName.py :

>>> def spam():
>>>     eggs = 'spam local'
>>>     print(eggs) # prints 'pam local'
>>> def bacon():
>>>     eggs = 'bacon local'
>>>     print(eggs) # prints 'bacon local'
>>>     spam()
>>>     print(eggs) # prints 'bacon local'
>>> eggs = 'global'
>>> bacon()
>>> print(eggs) # prints 'global'
bacon local
spam local
bacon local
global

在这个程序中,实际上有3个不同的变量, 但令人迷惑的是,它们都名为 eggs 。 这些变量是:

eggs = 'spam local'中,名为 eggs 的变量,存在于 spam() 被调用时的局部作用域;

eggs = 'bacon local'中,名为 eggs 的变量,存在于 bacon() 被调用时的局部作用域;

eggs = 'global'中,名为 eggs 的变量,存在于全局作用域。

因为这3个独立的变量都有相同的名字,追踪某一个时刻使用的是哪个变量,可能比较麻烦。这就是应该避免在不同作用域内使用相同变量名的原因。