Python中的作用域解析|LEGB规则

在这里,我们将讨论Python中的命名空间、作用域和LEGB规则等不同概念。

什么是Python中的命名空间

python命名空间是一个容器,其中名称映射到对象,它们用于避免在不同命名空间中存在相同名称的情况下发生混淆。它们由模块、函数、类等创建。

Python中的作用域是什么

作用域定义了必须搜索名称空间以获得名称到对象(变量)的映射的层次顺序。它是一个上下文,变量存在于其中,并从其中引用它们。它定义了变量的可访问性和生存期。让我们举一个简单的例子,如下所示:

pi = 'outer pi variable'
  
def print_pi():
    pi = 'inner pi variable'
    print(pi)
  
print_pi()
print(pi)

输出

inner pi variable
outer pi variable

上面的程序给出了不同的输出,因为相同的变量名pi驻留在不同的命名空间中,一个在函数print_pi中,另一个在上层。当print_pi()被执行时,'inner pi variable’被打印为函数命名空间内的pi值。当pi在外部命名空间中被引用时,输出值“outer pi variable”。从上面的例子中,我们可以猜测,在决定从哪个命名空间中选择变量时,肯定有一个遵循的规则。

Python中的作用域LEGB规则

在Python中,LEGB规则用于决定搜索命名空间以进行作用域解析的顺序。以下按层次结构列出了范围(从最高到最低/从最窄到最宽):

  • Local(L):定义在函数/类内部
  • Enclosed(E):定义在封闭函数内(嵌套函数概念)
  • Global(G):定义在全局(最上层)中
  • Built-in(B):Python内置模块中的保留名称

Python中的作用域解析|LEGB规则_第1张图片

Python中的局部作用域

局部作用域引用当前函数中定义的变量。函数总是会首先在其局部作用域中查找变量名。只有当它在那里没有找到它时,才检查外部范围。

# Local Scope
pi = 'global pi variable'
def inner():
    pi = 'inner pi variable'
    print(pi)
  
inner()

输出

inner pi variable

在运行上面的程序时,内部函数的执行打印其局部(LEGB规则中的最高优先级)变量pi的值,因为它在局部作用域中定义并可用。

局部和全局作用域

如果一个变量没有在局部范围中定义,则在更高的范围中检查它,在本例中是全局范围。

# Global Scope
pi = 'global pi variable'
def inner():
    pi = 'inner pi variable'
    print(pi)
  
inner()
print(pi)

输出

inner pi variable
global pi variable

因此,正如预期的那样,程序在执行inner()时打印出局部作用域中的值。这是因为它是在函数内部定义的,这是变量被查找的第一个地方。全局范围内的pi值在第8行执行print(pi)时打印。

局部、封闭和全局作用域

对于封闭的作用域,我们需要定义一个包含内部函数的外部函数,注释掉内部函数的局部pi变量,并使用nonlocal关键字引用pi。

# Enclosed Scope
pi = 'global pi variable'
  
def outer():
    pi = 'outer pi variable'
    def inner():
        # pi = 'inner pi variable'
        nonlocal pi
        print(pi)
    inner()
  
outer()
print(pi)

输出

outer pi variable
global pi variable

当outer()被执行时,inner()和相应的print函数被执行,它们打印所包含的pi变量的值。第10行的语句在inner的局部作用域中查找变量,但在那里找不到它。由于pi是用nonlocal关键字引用的,这意味着pi需要从外部函数(即外部作用域)访问。总而言之,pi变量在局部作用域中找不到,所以要查找更高的作用域。在封闭和全局作用域中都可以找到它。但是根据LEGB层次结构,即使我们在全局范围中定义了一个变量,也会考虑封闭的范围变量。

局部、封闭、全局和内置作用域

最后的检查可以通过从math模块导入pi并注释全局、封闭和局部pi变量来完成,如下所示:

# Built-in Scope
from math import pi
  
# pi = 'global pi variable'
  
def outer():
    # pi = 'outer pi variable'
    def inner():
        # pi = 'inner pi variable'
        print(pi)
    inner()
  
outer()

输出

3.141592653589793

由于pi没有在局部、封闭或全局作用域中定义,因此会查找内置作用域,即从数学模块导入的pi值。所以程序能够在最外层范围内找到pi的值。

你可能感兴趣的:(python,python)