📜  Python中的范围解析| LEGB规则

📅  最后修改于: 2020-05-11 14:10:06             🧑  作者: Mango

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

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

 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时,将输出值“ external pi variable “。 从上面的示例中,我们可以猜到肯定有一条规则可以遵循,以便确定必须从哪个名称空间中选择变量。

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

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


Local范围:
局部Local作用域是指在当前函数中定义的变量。函数将首先在其局部作用域中查找变量名。 只有在该处找不到它时,才检查外部作用域。

 # 局部Local作用域
  pi = 'global pi variable'
  def inner():
      pi = 'inner pi variable'
      print (pi)
 inner()

输出:

inner pi variable

在运行上述程序时, 内部函数的执行将打印其本地变量(LEGB规则中的最高优先级)变量pi的值,因为它是在本地范围内定义并可用的。

本地和全局范围:
如果未在局部范围内定义变量,则将在较高范围(在本例中为全局范围)中检查该变量。

 # 全局范围
  pi = 'global pi variable'
  def inner():
      pi = 'inner pi variable'
      print (pi)
 inner()
  print (pi)

输出:

inner pi variable
global pi variable

因此,按预期,程序会在执行inner()时在本地范围内打印出该值。 这是因为它是在函数内部定义的,这是查找变量的第一位。 在第9行执行print(pi)时 ,将打印全局范围内的pi值。

局部,封闭和全局范围:
对于封闭的范围,我们需要定义一个封闭内部函数的外部函数,注释掉内部函数的本地pi变量,并使用nonlocal关键字引用pi 。

 # 封闭范围
  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

当执行external()时,将执行inner()并随后执行打印函数,该函数将打印在封闭的pi变量。 第10行中的语句在inner的局部范围寻找变量,但在那里找不到它。 由于pi是使用nonlocal关键字引用的,因此意味着pi需要从外部函数(即外部范围)进行访问。 总而言之,在局部作用域中找不到pi变量,因此将查找更高的作用域。 在封闭范围和全局范围中都可以找到它。 但是按照LEGB层次结构,即使我们在全局范围中定义了一个变量,也要考虑封闭的范围变量。

本地,封闭,全局和内置范围:
可以通过从数学模块导入pi并注释全局,封闭和局部pi变量来完成最终检查,如下所示:

 # 内置范围
  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