美文网首页
Python关于LEGB 的一个坑

Python关于LEGB 的一个坑

作者: 规划好哼哼哼哼哼20999 | 来源:发表于2016-10-23 15:35 被阅读0次

今天在编程中遇到一个问题,思考半天,原来是因为对LEGB规则没有深入理解。

import pprint

def pprint(dic_things):

    ehco = pprint.PrettyPrinter(width = 1 ,indent = 4)

    echo.pprint(dic_things)

pprint({'a':'1','b':'2','c':'5'})

AttributeError: 'function' object has no attribute 'PrettyPrinter'

心中一阵懵逼,为啥引用不了呢。难道函数内不能使用import模块。分析一番,原来是要运用LEGB大法,这也是就python编译器的执行规则。

Python 使用 LEGB 的顺序来查找一个符号对应的对象

locals ->enclosing function -> globals -> builtins

那么我们来分析分析,这个错误吧。

Python 是动态语言,def 实际上是执行一条指令,用来创建函数(class 则是创建类的指令),而不仅仅是个语法关键字。函数并不是事先创建好的,而是执行到的时候才创建的。

Python语言函数代码的执行流程,为了保证函数的定义先于其首次调用时执行,我们需要知道中语句的执行顺序。

执行总是从程序的第一行代码开始的,从上到下,从左到右,按顺序依次执行第一条语句。

函数定义并不会改变程序的执行流程,但应该注意函数代码块中的语句并不是立即就执行的,而是等到函数被程序调用时才会执行。

函数调用可以看作程序执行流程中的一个迂回路径,遇到函数调用时,并不会直接继续执行下一条语句,而是跳到函数体的第一行,继续执行完函数代码块的所有语句,再跳回到原来离开的地方。

看似比较简单,一会你会发现,函数代码块中可以调用其他函数,当程序流程运行到一个函数之中时,可能需要执行其他函数中的语句。但当执行那个函数中的语句时,又可能再需要调用执行另一个函数的语句。

幸好Python对于它运行到哪里有很好的记录,所以在每个函数执行结束之后,程序都能跳回到它离开的那个地方,直到执行到整个程序的结尾,才会结束程序。

两个片段解释的很清楚,当我们执行到

pprint({'a':'1','b':'2','c':'5'})

python解释器首先在当前命名空间内寻找变量pprint,非常惊喜他找到了,一个函数名为pprint,

OK,放弃寻找并且执行这个函数(如此我们引入的指向模块的pprint变量就被忽略了),函数执行以后,在函数内部第一句

ehco = pprint.PrettyPrinter(width = 1 ,indent = 4)

我们的变量pprint这时已经指向了函数pprint,肯定就会报错啦,没有这个方法。

那么修改一下,这次执行成功了,分析一下吧。

import pprint

def pprint(dic_things,pprint = pprint):

    pprint = pprint.PrettyPrinter(width = 1 ,indent = 4)

    pprint.pprint(dic_things)

pprint({'a':'1','b':'2','c':'5'})

老套路,发现

pprint({'a':'1','b':'2','c':'5'})

在自己的命名空间找,发现特殊语句def pprint,很好执行这个函数,这里出现了我们解决问题的关键,pprint = pprint,这里这个给pprint赋值的pprint(好吧,只能这么绕口),为什么就是我们想要的那个身为moudule的pprint.呢?首先从缩进上判断,他缩进为主行缩进(就是没有缩进),也就是说他的命名空间和

pprint({'a':'1','b':'2','c':'5'})

一致,但是他又是与def pprint同行也就是同时创建,那么当解释器准备解释pprint = pprint这句话时,这个命名空间中并没有(function)pprint这个变量!!!怎么办,python解释器就会向外层寻找,这样就找到了我们的(module)pprint。

其实最好的办法还是,引入时就把名字改了

import pprint as pprint_module

这样就避免名字相同,我们还要用人脑去捋顺他的程序执行套路,不过也好,这个坑清晰了两个问题。

1.定义函数时,函数的参数的命名和函数体本身同级,并且他俩同时创建。

2.可以通过缩进来辅助确定一个变量的命名空间(不一定)

PYTHON的作用域由def、class、lambda等语句产生,if、try、for等语句并不会产生新的作用域。变量名引用分为三个作用域进行查找:首先是本地,然后是函数内(如果有的话),之后是全局,最后是内置。

相关文章

  • Python关于LEGB 的一个坑

    今天在编程中遇到一个问题,思考半天,原来是因为对LEGB规则没有深入理解。 import pprintdef pp...

  • 2018-03-20作用域和添加实例属性和方法

    一、LEGB 规则 Python 使用 LEGB 的顺序来查找一个符号对应的对象 locals -> enclos...

  • 十:Python之LEGB规则

    Python在查找 ‘ 名称‘ 时,是按照LEGB规则查找的: Local --> Enclosed --> Gl...

  • python闭包和装饰器

    一、python函数作用域LEGB python解释器查找变量的原则(顺序):L→E→G→BL:Local函数内部...

  • Python | LEGB规则

    LEGB的名字取自: Locals :当前命名空间,如函数或模块 Enclosing :外部嵌套函数的命名空间(闭...

  • Python LEGB规则

    本篇总结了Python中的命名空间及LEGB原则 写在前面的话之所以有这篇总结,是因为在当初学习及使用Python...

  • python的LEGB规则

    https://blog.csdn.net/MCANDML/article/details/78501573#t0

  • python基础2.2 True+True

    python的作用域规则:LEGB原则 为什么Python会认为两个完全不同的对象拥有相等的值?在Python中布...

  • Python高级编程之装饰器(一)

    请移步:https://vergilben.top/ Python高级编程之装饰器(一) 1、函数作用域LEGB ...

  • Python中的LEGB规则

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

网友评论

      本文标题:Python关于LEGB 的一个坑

      本文链接:https://www.haomeiwen.com/subject/pdkkuttx.html