zoukankan      html  css  js  c++  java
  • Python的程序结构[3] -> 变量/Variable[1] -> LEGB 法则

    LEGB法则 / LEGB Rule


     

    LEGB 变量搜索顺序


    ---- 来源于《Python学习手册》/ Learning Python Page 419 ----

    Python 的变量名解析机制称为  LEGB 法则。

    L – Local: 本地作用域;

    E – Enclosing: 上一层结构中 def 或 lambda 的本地作用域;

    G – Global: 全局作用域;

    B – Build-in: 内置作用域。

    LEGB作用域查找原则:当引用一个变量时,Python 按以下顺序依次进行查找:从本地变量中,在任意上层函数的作用域,在全局作用域,最后在内置作用域中查找。第一个能够完成查找的就算成功。变量在代码中被赋值的位置通常就决定了它的作用域。在 Python3.0 中,nonlocal 声明也可以迫使名称映射到函数内部的作用域中,而不管是否对其赋值。这些规则仅对简单的变量名有效。

    下面用代码示例来说明这一查找原则。

    """
    Python LEGB rule: local, enclosing, global, built-in
    """

     

    L 查找


    定义三个函数用于测试 Local 搜索,correct 函数在调用 A 之前进行了 global 声明,调用了全局变量 A,而 error 函数在调用之前没有进行 global 声明。使用 try/except 语句对报错进行捕获处理。correct_2 函数在调用前对 A 进行赋值,因为没有进行 Global 声明此处的 A 是局部变量 A,对其赋值不影响全局变量 A。

     1 # Local -- L  
     2 A = 7
     3 def errorFuncLocal():  
     4     print('
    -------------Func: errorFuncLocal----------------')  
     5     try:  
     6         print('The global value of A is %d' % A)  
     7     except NameError:  
     8         print('Function <errorFuncLocal> raises a NameError')  
     9     A = 6  
    10       
    11 def correctFuncLocal():  
    12     print('
    -------------Func: correctFuncLocal------------')  
    13     global A  
    14     try:  
    15         print('The global value of A is %d' % A)  
    16     except NameError:  
    17         print('Function <correctFuncLocal> raises a NameError')  
    18     # A = 6  
    19       
    20 def correctFuncLocal_2():  
    21     print('
    -------------Func: correctFuncLocal_2------------')  
    22     A = 5  
    23     try:  
    24         print('The local value of A is %d' % A)  
    25     except NameError:  
    26         print('Function <correctFuncLocal> raises a NameError')  

    Note: 在 errorFuncLocal 函数中,需要在局部变量中对变量 A 进行操作,否则局部没有变量 A 的操作,则 L 搜索找不到 A,而 G 搜索中会找到 A,从而引入全局变量 A,而无法引发局部变量 A 的 NameError。

    1 if __name__ == '__main__':  
    2     errorFuncLocal()  
    3     correctFuncLocal()  
    4     correctFuncLocal_2()  
    5     print('The global value of A is %d' % A)  

    运行上面的代码可以得到输出为,

    -------------Func: errorFuncLocal----------------
    Function <errorFuncLocal> raises a NameError
    
    -------------Func: correctFuncLocal------------
    The global value of A is 7
    
    -------------Func: correctFuncLocal_2------------
    The local value of A is 5
    The global value of A is 7

    可以看到,

    errorFuncLocal 函数中由于没有进行 global 声明,且又对变量 A 进行了赋值,最终导致了错误异常,

    correctFuncLocal 函数中进行了 global 声明,因此没有产生报错,

    correctFuncLocal_2 函数中,定义了 A 实际上是一个局部变量,可以看到,在函数内部 A 为 5,但函数外部的全局变量 A 依旧为 7,在使用时 L 搜索优先找到的是局部变量的 A。


    E 查找


    再定义两个函数用于测试 Enclosing 搜索,

     1 # Enclosing -- E  
     2 A = 7
     3 def errorFuncEnclosing():  
     4     print('
    -------------Func: errorFuncEnclosing-----------')  
     5     def foo():  
     6         print('The enclosing value of A is %d' % A)  
     7     try:  
     8         foo()  
     9         A = 6  
    10     except NameError:  
    11         print('Function <errorFuncEnclosing> raises a NameError')  
    12       
    13 def correctFuncEnclosing():  
    14     print('
    -------------Func: correctFuncEnclosing-----------')  
    15     def foo():  
    16         print('The enclosing value of A is %d' % A)  
    17     try:  
    18         A = 6  
    19         foo()  
    20     except NameError:  
    21         print('Function <errorFuncEnclosing> raises a NameError')  

    运行函数

    1 if __name__ == '__main__':  
    2     errorFuncEnclosing()  
    3     correctFuncEnclosing()  
    4     print('The global value of A is %d' % A)  

    最终输出的结果如下,由于correct 函数的内层函数调用 A 之前,在外层函数中定义了 A,从而不会引发 NameError,而 error 函数在内层函数调用A之后才对 A 进行赋值操作,Enclosing 搜索在外层函数中找到了变量 A,但是在调用之前未进行赋值操作,因此会引发一个 NameError。

    -------------Func: errorFuncEnclosing-----------
    Function <errorFuncEnclosing> raises a NameError
    
    -------------Func: correctFuncEnclosing-----------
    The enclosing value of A is 6
    The global value of A is 7


    G 查找


    定义一个函数用于验证全局变量查找,

    1 # Global -- G  
    2 A = 7
    3 
    4 def correctFuncGlobal():  
    5     print('
    -------------Func: correctFuncGlobal-----------')  
    6     print('The global value of A is %d' % A)  

    在函数内部直接调用 A,由于 LE 搜索都没找到变量 A,而 G 搜索找到了,因此此时的变量 A 是全局变量。

    -------------Func: correctFuncGlobal-----------
    The global value of A is 7

    B 查找


    最后,B 查找搜索为内建变量查找,而对于内建变量,例如 __name__,在 LEG 搜索都没找到后启用 B 搜索才可以查找到内建变量,因此可以直接引用内建变量。

    1 # Built-in -- B  
    2 def correctFuncBuildin():  
    3     print('
    -------------Func: correctFuncBuildin-----------')  
    4     print('The value of built-in variable __name__ is:', __name__) 
    5 
    6 if __name__ == '__main__':  
    7     correctFuncBuildin()  

    结果如下,

    -------------Func: correctFuncBuildin-----------
    The value of build-in variable __name__ is: __main__

    参考链接


    http://www.jb51.net/article/84206.htm

  • 相关阅读:
    第01组 团队Git现场编程实战
    2019 SDN上机第1次作业
    第二次结对编程作业
    团队项目-需求分析报告
    团队项目-选题报告
    2019 SDN阅读作业
    2019 SDN上机第3次作业
    2019 SDN上机第2次作业
    2019 SDN上机第1次作业
    OpenDayLight安装Features
  • 原文地址:https://www.cnblogs.com/stacklike/p/8099034.html
Copyright © 2011-2022 走看看