Python中的LEGB规则

  
  前言   
  

  理解LEGB前,首先需要对Python的作用域,命名空间有一定的了解,话题才能继续展开。   

  

     

  

  命名空间表示变量的可见范围,一个变量名可以定义在多个不同的命名空间,相互之间并不冲突,但同一个命名空间中不能有两个相同的变量名。比如:两个叫“张三”的学生可以同时存在于班级一个和班级B中,如果两个张三都是一个班级,那么带来的麻烦复杂很多了,在Python中你不能这么干。   

  

  在Python中用字典来表示一个命名空间,命名空间中保存了变量(名字)和对象的映射关系,在Python中命名空间出现在哪些地方呢?有函数范围内的命名空间(本地),有模块范围内的命名空间(全球),有Python内建的命名空间(内置),还有类对象的所有属性组成的命名空间。   

  

     

  

  所有的命名空间都是有生命周期的,对于python内建的命名空间,python解析器启动时创建,一直保留直至直python解析器退出时才消亡。而对于函数的当地命名空间是在函数每次被调用的时候创建,调用完成函数返回时消亡,而对于模块的全球命名空间是在该模块被导入的时候创建,解析器退出时消亡。   

  

     

  

  一个作用域是指一段程序的正文区域,可以是一个函数或一段代码。一个变量的作用域是指该变量的有效范围.Python的作用域是静态作用域,因为它是由代码中得位置决定的,而命名空间就是作用域的动态表现。   

  

     

  

  Python2.2之前定义了三个作用域,分别是:   

  

  全球作用域,对应的全球命名空间,一个模块最外层定义的一个作用域。   
  当地的作用域,对当地应命名空间,由函数定义的。   
  内装式作用域,对应装入的命名空间,python内部定义的最顶层的作用域,在这个作用域里面定义了各种内建函数:开放、范围,xrange、列表等等。   
  那时的Python作用域规则叫做1规则,变量(名字)的引用按照当地作用域,全球作用域,装入的作用域的顺序来查找。   

  

  首先来看一段代码:   

  <前>   a =1   ,def  foo ():   ,,,a =2   ,,,print  a ,,//[1],   print  a ,,,,,,//[2]   ,   foo ()   之前   

  [1]处输出结果为2,Python首先会在函数foo定义的地方作用域中查找名字,如果找到了直接输出,没有没找到就会在模块定义的全球作用域中查找,如果还没找的到,就到Python内建的内装式作用域中查找,如果还没找到就报异常:NameError:名字' a '不是定义。   

  

  [2]处输出结果为1,查找顺序同样是按照LGB规则,只不过这里的地方作用域就是全球作用域。   

  
  LEGB规则   
  

  Python2.2开始引入嵌套函数,嵌套函数为python提供了闭包实现。   

  <前>   时间=a  1 def  foo ():   ,,a =2   ,,def 酒吧():   ,,,,,,,print  a ,//[1],,,, return 酒吧   ,   时间=func  foo ()   函数()   之前   

  函数酒吧和=2捆包在一起组成一个闭包,因此这里=2即使脱离了foo所在当地的作用域,但调用函数的时候(其实就是调用bar)查找名字一个的顺序是LEGB规则,这里的E就是封闭的缩写,代表的“直接外围作用域”这个概念。查找时,在酒吧对应的地方作用域中没有时,然后在它外围的作用域中查找a.LEGB规定了查找一个名称的顺序为:当地→封闭→全球→内置命令。   

           
         Python中的LEGB规则            

  原文来自:开源中国侵删   

  

  
  

Python中的LEGB规则