[关闭]
@zhangyu756897669 2017-08-22T15:36:21.000000Z 字数 3128 阅读 545

python官方文档9.0

python官方文档


全球范围和本地范围

  1. 被调用函数中分配的参数和变量据说存在于该函数的局部作用域中。在所有功能之外分配的变量据说存在于全局范围内。存在于本地范围内的变量称为局部变量,而全局范围中存在的变量称为全局变量。一个变量必须是一个或另一个;它不能是本地和全球。
  2. 将范围视为变量的容器。当范围被破坏时,存储在范围变量中的所有值都被遗忘。只有一个全局范围,它是在程序开始时创建的。当程序终止时,全局范围被破坏,其所有变量都被遗忘。否则,下次运行程序时,变量会记住上次运行时的值。
  3. 每当调用函数时都会创建一个本地范围。在此函数中分配的任何变量都存在于本地范围内。当函数返回时,局部范围被破坏,这些变量被遗忘。下次调用此函数时,局部变量将不会记住上次调用函数时存储的值。
  4. 范围很重要的原因有几个:

    • 全局范围内的代码不能使用任何局部变量。
    • 但是,本地范围可以访问全局变量。
    • 函数本地范围中的代码不能在任何其他本地范围内使用变量。
    • 如果不同的变量在不同的范围内,可以使用相同的名称。也就是说,可以有一个名为spam的局部变量,还有一个名为spam的全局变量。
  5. 原因是Python具有不同的范围,而不仅仅是使全局变量成为一个全局变量,这样当变量被特定的函数调用中的代码修改时,该函数只能通过其参数和返回值与程序的其余部分进行交互。这缩小了可能导致错误的列表代码行。如果您的程序仅包含全局变量,并且由于将变量设置为错误值而发生错误,那么很难跟踪此错误值的设置。它可以从程序中的任何地方设置 - 您的程序可能是数百或数千行!但是,如果错误是因为本地变量的值不正确,那么只知道该函数中的代码只能设置不正确。

  6. 尽管在小程序中使用全局变量是正确的,但随着程序越来越大,依赖于全局变量是个不好的习惯。

本地变量不能在全局范围内使用

输入这个程序,运行它会导致错误:

  1. def spam():
  2. eggs = 31337
  3. spam()
  4. print(eggs)

如果您运行此程序,输出将如下所示:

  1. Traceback (most recent call last):
  2. File "C:/test3784.py", line 4, in <module>
  3. print(eggs)
  4. NameError: name 'eggs' is not defined

发生错误是因为egg变量仅存在于调用spam()时创建的本地作用域中。一旦程序执行从垃圾邮件返回,该本地范围将被销毁,并且不再有名为egg的变量。所以当你的程序试图运行打印(鸡蛋)时,Python会给你一个错误,表示没有定义蛋。如果你这么想,这是有道理的当程序执行在全局范围内时,不存在本地作用域,因此不能有任何局部变量。这就是为什么在全局范围内只能使用全局变量的原因。

本地作用域不能在其他本地作用域中使用变量

每当调用函数时都会创建一个新的本地范围,包括当从另一个函数调用函数时。运行这个程序:

  1. def spam():
  2. eggs = 99
  3. bacon()
  4. print(eggs)
  5. def bacon():
  6. ham = 101
  7. eggs = 0
  8. spam()

程序启动时,将spam()函数称为❺,并创建一个本地作用域。局部变量egg❶设置为99.然后将bacon()函数称为❷,并创建第二个本地范围。多个本地范围可以同时存在。在这个新的本地范围内,局部变量ham设置为101,并且还创建了与spam()的本地范围不同的局部变量egg,并将其设置为0。
当bacon()返回时,该调用的本地作用域被销毁。在spam()函数中继续执行程序执行以打印蛋❸的值,并且由于本地调用spam()的范围仍然存在于这里,因此将egg变量设置为99.这是程序打印的内容。
结果是,一个函数中的局部变量与另一个函数中的局部变量完全分离。

全局变量可以从本地范围读取

运行程序:

  1. def spam():
  2. print(eggs)
  3. eggs = 42
  4. spam()
  5. print(eggs)

由于没有名为egg的任何参数或任何为spam()函数赋值的代码,因此当使用spam()函数时,Python将其视为对全局变量egg的引用。这就是为什么当前一个程序运行时打印42。

具有相同名称的本地和全局变量

为了简化您的生活,请避免使用与全局变量或其他局部变量具有相同名称的局部变量。但从技术上讲,在Python中这样做是完全合法的。运行程序:

  1. def spam():
  2. eggs = 'spam local'
  3. print(eggs) # prints 'spam local'
  4. def bacon():
  5. eggs = 'bacon local'
  6. print(eggs) # prints 'bacon local'
  7. spam()
  8. print(eggs) # prints 'bacon local'
  9. eggs = 'global'
  10. bacon()
  11. print(eggs) # prints 'global'

当您运行此程序时,它输出以下内容:

bacon local
spam local
bacon local
global

全球声明

如果需要从函数内修改全局变量,请使用全局语句。如果在函数顶部有一个全局蛋的行,它会告诉Python,“在这个函数中,egg是指全局变量,所以不要用这个名称创建一个局部变量”。输入以下代码:

  1. def spam():
  2. global eggs
  3. eggs = 'spam'
  4. eggs = 'global'
  5. spam()
  6. print(eggs)

当您运行此程序时,最终的print()调用将会输出:

  1. spanm

有四个规则来判断一个变量是在一个局部作用域还是在全局范围内:

为了更好地了解这些规则,以下是一个示例程序。

  1. def spam():
  2. global eggs
  3. eggs = 'spam' # this is the global
  4. def bacon():
  5. eggs = 'bacon' # this is a local
  6. def ham():
  7. print(eggs) # this is the global
  8. eggs = 42 # this is the global
  9. spam()
  10. print(eggs)

在spam()函数中,鸡蛋是全球蛋变量,因为在函数开始处有一个全球性的蛋类声明❶。在培根()中,蛋是一个局部变量,因为在该函数中有一个赋值语句❷。在ham()❸中,eggs是全局变量,因为在该函数中没有赋值语句或全局语句。运行程序,将出现以下结果:

  1. spam

注意

  1. 如果您想要从函数中修改存储在全局变量中的值,则必须对该变量使用全局语句。如果您在为其分配值之前尝试在函数中使用本地变量,那么与以下程序一样,Python会给您一个错误。
  1. def spam():
  2. print(eggs) # ERROR!
  3. eggs = 'spam local'
  4. eggs = 'global'
  5. spam()

如果运行上一个程序,则会产生错误消息。

Traceback (most recent call last):
File "C:/test3784.py", line 6, in
spam()
File "C:/test3784.py", line 2, in spam
print(eggs) # ERROR!
UnboundLocalError: local variable 'eggs' referenced before assignment

发生这种错误是因为Python看到在spam()函数❶中有一个适用于蛋的赋值语句,因此认为蛋是本地的。但是,因为打印(鸡蛋)在鸡蛋被分配任何东西之前执行,所以局部变量蛋不存在。 Python不会回到使用全局的蛋变量❷。

此功能为“黑匣子”

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注