Python的程序结构[3] -> 变量/Variable -> 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(‘\n-------------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(‘\n-------------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(‘\n-------------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(‘\n-------------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(‘\n-------------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(‘\n-------------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(‘\n-------------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

时间: 2024-08-29 18:13:07

Python的程序结构[3] -> 变量/Variable -> LEGB 法则的相关文章

Python的程序结构[4] -&gt; 函数/Function -&gt; 匿名函数

匿名函数 / Anonymous Function 匿名函数是一种不需要绑定函数名的函数 (i.e. functions that are not bound to a name).匿名函数通过 lambda 表达式进行构建.常用于快速建立起一个(一次性的)函数. Note: lambda 是 Python 的一个表达式/关键字,类似 return,并非一个函数,而是能够生成匿名函数. 关于匿名函数的使用,可以用下面的方式,直接使用, 1 # Use directly 2 f = lambda

Python的程序结构(2) -&gt; 方法/Method -&gt; 静态方法、类方法和属性方法

静态方法.类方法和属性方法 在 Python 中有三种常用的方法装饰器(参考装饰器部分内容),可以使普通的类实例方法变成带有特殊功能的方法,分别是静态方法.类方法和属性方法. 静态方法 / Static Method 在 def 定义之前加上 @staticmethod 进行装饰,便可以使该方法成为静态方法,静态方法无法调用实例属性.静态方法可以通过实例或类进行调用.通常用于无需生成实例或无需共享实例属性的方法中,比如一些纯粹的数学公式计算等场合. 1 class Foo(): 2 @stati

Python的程序结构[2] -&gt; 类/class -&gt; 类的特殊属性

类的特殊属性 / Special Property of Class Python 中通过 class 进行类的定义,类可以实例化成实例并利用实例对方法进行调用. 类中还包含的一些共有的特殊属性. 特殊类属性 含义 __name__ 类的名字(字符串) __doc__ 类的文档字符串 __bases__ 类的所有父类组成的元组 __dict__ 类的属性组成的字典 __module__ 类所属的模块 __class__ 类对象的类型 1 class Foo(): 2 """

Python的程序结构[2] -&gt; 类/Class -&gt; 内建类 bytes 和 bytearray

内建类 bytes 和 bytearray / Built-in Type bytes and bytearray 关于内建类 Python的内建类 bytes 主要有以下几点: class bytes([source[, encoding[, errors]]]) Return a new "bytes" object, which is an immutable sequence of integers in the range 0 <= x < 256. bytes

第五章 C程序结构

一.数值类型 1.实数常量的表示:3.5(双精度),3.5f(单精度),3.5L(长双精度) 2.整数常量:char字符常量('a','b','0')当做一个整型常量参加运算 3.数字字符与英文字母字符的编号(Ascll码)都是顺序连接的 二.控制语句 1.while和do while的区别:当while条件不成立时,while()循环不执行循环语句,而do while会循环执行一次循环语句再判断 2.流程控制语句:continue(中断本次循环)    break(跳出整个循环) 3.开关语句

【Python】05、python程序结构控制语句

一.程序结构 程序结构:语句和表达式按照什么样的顺序执行 所有语言无非就三种程序结构:        顺序:默认结构 语句从上到下依次一行一行的执行,        分支:选择一个分支执行,永远最多只执行一个分支        循环: 二.分支结构语句 1.Python的比较操作 所有的Python对象都支持比较操作,可用于测试相等性.相对大小等 如果是复合对象,Python会检查其所有部分,包括自动遍历各级嵌套对象,直到可以得出最终结果 测试操作符: " =="操作符测试值的相等性

Python 变量作用域 LEGB

回顾 - Decorator 前篇有讲到了, 闭包和装饰器的概念. 闭包就是, 函数内部嵌套函数. 而 装饰器只是闭包的特殊场景而已, 特殊在如果外函数的参数是指向一个, 用来被装饰的函数地址时(不一定是地址哈, 随意就好) , 就有了 "@xxx" 这样的写法, 还是蛮有意思的. 装饰器的作用是 在不改变原函数的代码前提下, 额外给原函数填写新功能. 写法上来看, 还是比较简洁优雅的. 装饰器的通俗写法 # 装饰器的通用写法 def out(func): def inner(*arg

黑马程序员---C基础3【变量的易错】【程序结构】【if语句】【Switch语句】

------Java培训.Android培训.iOS培训..Net培训.期待与您交流! ------- [变量的易错] 1.变量为什么要初始化为0 int  sum,a=3: sum = sum+a 如果未初始化则会成为一个不确定的变量,结果也会不确定,容易出错. 2.不同类型的变量之间的转换 切记int  a=1,b=0:b=1-1.5:其中b为一个整型所有结果是保留整数部分的0,而不是-0.5,又因为0没有正负之分,所有保存结果为b=0: 3.关于Xcode的一个快速注释的插件 快捷键://

python基础(3)—— 程序结构

python和其他的编程语言一样,也有三种程序结构.顺序结构,选择结构,循环结构. 1.顺序结构 顺序结构按照顺序执行程序,不做过多解释. 2.选择结构     2.1 if 语句 if condition: expression 示例: [[email protected]]# cat if.py #!/usr/bin/env python if 3 < 5: print "3 less than 5" # 语句块里面可以是多个语句if 3 > 4: print &quo