3小时入门Python——第二十五课作用范围

  |   0 评论   |   0 浏览   |   给我丶鼓励

范围是其中某些变量可以通过其名称来达成的程序的一部分。范围是编程中非常重要的概念,因为它定义了代码块中名称的可见性。

全局与局部

当您定义变量时,它将变为全局局部。如果在模块的顶层定义了变量,则将其视为全局变量。这意味着您可以在程序的每个代码块中引用此变量。当您需要在不同功能之间共享状态信息或某些配置时,全局变量会很有用。例如,您可以将当前用户的名称存储在全局变量中,然后在需要时使用它。它使您的代码更易于更改:要设置新的用户名,您只需更改一个变量。

在函数主体中定义局部变量时会创建它们。因此,其名称只能在当前函数的作用域内解析。它使您避免使用全局变量时可能发生的副作用问题。

考虑示例以查看全局变量和局部变量之间的区别:

phrase = "Let it be"
 
def global_printer():
    print(phrase)  # we can use phrase because it's a global variable
 
global_printer()  # Let it be is printed
print(phrase)  # we can also print it directly
 
phrase = "Hey Jude"
 
global_printer()  # Hey Jude is now printed because we changed the value of phrase
 
def printer():
    local_phrase = "Yesterday"
    print(local_phrase)  # local_phrase is a local variable
 
printer()  # Yesterday is printed as expected
 
print(local_phrase)  # NameError is raised

因此,既可以从模块的顶层也可以从函数的主体访问全局变量。另一方面,局部变量仅在最近的作用域内部可见,而不能从外部访问。

LEGB 规则

Python 中的可变分辨率遵循 LEGB 规则。这意味着解释器按以下顺序查找名称:

  1. 局部。在函数体内定义且未声明为全局的变量。
  2. 封闭。从内部到外部,所有封闭函数中的局部作用域名称。
  3. 全局。在模块的顶级定义的名称或使用 global 关键字声明为全局的名称。
  4. 内置。Python 中的任何内置名称。

让我们考虑一个示例来说明 LEGB 规则:

x = "global"
def outer():
    x = "outer local"
    def inner():
        x = "inner local"
        def func():
            x = "func local"
            print(x)
        func()
    inner()
 
outer()  # "func local"

print() 调用内部的函数时 func(),解释器需要解析名称 x。首先查看最里面的变量,然后搜索 x in func() 函数的局部定义。在上面的代码的情况下,解释会发现当地 xfunc() 成功并打印其价值,'func local'。但是,如果没有 x in 的定义 func() 怎么办?然后,口译员将向外移动并开始 inner() 工作。查看以下示例:

x = "global"
def outer():
    x = "outer local"
    def inner():
        x = "inner local"
        def func():
            print(x)
        func()
    inner()
 
outer()  # "inner local"

如您所见,名称 x 已在 inner() 函数中解析,因为 "inner local" 已打印了值。

如果我们也 xinner() 函数中删除的定义并再次运行代码,则解释器将以 outer() 相同的方式继续在局部语言中搜索。如果我们继续删除定义的代码行 x,则解释器将继续使用 outer() 局部变量,然后是全局变量,然后是内置名称。如果没有匹配的内置名称,将引发错误。看一下 x 解释器达到的全局定义的示例:

x = "global"
def outer():
    def inner():
        def func():
            print(x)
        func()
    inner()
 
outer()  # "global"

如果您打算使用封闭函数,请不要忘记 LEGB 规则。

关键字“非局部”和“全局”

我们已经提到了分配全局变量的一种方法:在模块的顶层进行定义。但是,还有一个特殊的关键字 global 允许我们在函数体内声明全局变量。

如果不使用 global 关键字,则无法在函数内部更改全局变量的值:

x = 1
def print_global():
    print(x)
 
print_global()  # 1
 
def modify_global():
    print(x)
    x = x + 1
 
modify_global()  # UnboundLocalError

出现错误是因为我们试图将 x 包含的表达式分配给局部变量,x 并且解释器无法在局部范围内找到此变量。要解决此错误,我们需要声明 x 全局:

x = 1
def global_func():
    global x
    print(x)
    x = x + 1
 
global_func()  # 1
global_func()  # 2
global_func()  # 3

如果 x 是全局性的,你可以增加它的功能内在价值。

nonlocal 关键字使我们可以为外部(而不是全局)范围内的变量赋值:

def func():
    x = 1
    def inner():
        x = 2
        print("inner:", x)
    inner()
    print("outer:", x)
 
def nonlocal_func():
    x = 1
    def inner():
        nonlocal x
        x = 2
        print("inner:", x)
    inner()
    print("outer:", x)
 
func()  # inner: 2
        # outer: 1
 
nonlocal_func()  # inner: 2
                 # outer: 2

尽管 global 并且 nonlocal 存在于语言中,但它们在实践中并不经常使用,因为这些关键字使程序难以预测且难以理解。

为什么需要示波器?

首先,为什么 Python 需要区分全局范围和局部范围?好吧,从其他一些没有_局部_作用域的编程语言的经验来看,很清楚,仅使用全局作用域是非常不便的:当从代码的每个部分都可以访问每个变量时,必然会发生大量错误。代码越长,记住所有变量的名称就越困难,而不会意外地更改您原本应该保持不变的变量的值。因此,Python 允许您在将代码拆分为函数时将其与其余代码“隔离”起来,从而省去了麻烦。

另一方面,为什么我们需要_全局_范围呢?好的,正如上面已经提到的,全局范围是在函数调用之间保留信息的最简单方法之一:尽管局部变量在函数返回时就消失了,但全局变量仍然存在,并有助于函数之间相互交换必要的数据。同样,全局变量可以启用更复杂的进程之间的通信,例如多线程应用程序中的线程。


标题:3小时入门Python——第二十五课作用范围
作者:给我丶鼓励
地址:https://blog.doiduoyi.com/articles/1593925888214.html

评论

发表评论