python命名规则_python中的命名空间和LEGB规则

fec118b935a26283dd99bfc0d06dbcdd.gif

说到命名空间,大家应该很熟悉,比如C++的namespace,又或者大名鼎鼎的docker就是利用Linux的namespace实现的。Python中也有namespace的概念,但不管哪个领域,namespace的作用都是一样的,就是为了区分和划分资源。

你应该已经知道,Python里一切都是对象,变量,函数,列表,字典和类等都是对象,那如何在程序里访问对象,那就是name to object. 比如用a="hello world"进行一个简单字符串的赋值,就是创建了a的变量名去引用“hello world”对象。

我们可以把名称空间想象成一个Python字典结构,其中键表示变量名,值表示对象,这也是当前Python中实现namespace的方式。例如:

x_namespace={name_a:object_a, name_b:object_b,...}。

当然Python肯定会存在多个独立的命名空间,变量名重复的情况,例如:

x_namespace={name_a:object_a, name_b:object_b,...}

y_namespace={name_a:object_c, name_b:object_d,...}

命名空间除了相互独立外,还有自己的作用域。作用域定义了Python程序根据不同范围级别去查找关联对象的变量名。说白了就是,变量在什么范围里可以被访问到。我觉得作用域可以分为局部,enclosed,全局和内置。

所谓LEGB,分别代表了local,enclosed,global和built-in。看字幕排序也知道了,查找变量名会根据这个四个namespace作用域的排序依次查找。local->enclosed->global->built-in.

  • 局部,在函数或类方法内部。

  • Enclosed,一个函数被包装在另一个函数中,请查阅闭包概念。

  • 全局,执行脚本本身的最高层。

  • 内置,是Python为自己保留的特殊namespace。

所以,如果变量名在局部作用域中找不到,就会搜索enclosed命名空间。如果enclosed命名空间找不到,Python将转到全局命名空间,如果还是搜不到,它将搜索内置命名空间,如果在任何namespace中都找不到变量名,则会引发NameError异常。

Sample:

i = 0def fun():    print(i, "inside fun")fun()print(i, "outside")

按照LEGB规则,执行print(i, "inside fun"),会在fun函数自己的局部namespace查找i,这里没有找到,当然这里没有用到enclosed,所以再向全局namespace,这里找到了i。执行print(i, "outside"),首先会在自己的全局namespace查找,这里找到了i,所以运行结果:

0 inside fun0 outside

你可以用内置函数locals()和globals(),查找局部变量/全局变量和对象的字典映射。

i = 0def fun():    print(locals())    print(i, "inside fun")fun()print(globals())print(i, "outside")

运行结果

{}0 inside fun{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.sourcefileloader object at>, '__spec__': None, '__annotations__': {}, '__builtins__': , '__file__': 'C:/Users/think/PycharmProjects/learnpytest/a.py', '__cached__': None, 'i': 0, 'fun': }0 outside

global和nonlocal 关键字

如果你想在局部作用域里修改里修改全局变量,可以在局部作用域里使用global关键字。

如果你想在局部作用域里修改enclosed作用域(外部嵌套函数)的的变量,可以在局部作用域里使用nonlocal关键字。

比如

i = 0def fun():    global i    i = 2    print(i, "inside fun")fun()print(i, "outside")

运行结果

2 inside fun2 outside

for 循环

与其他一些编程语言不同,for循环里的作用域就是for本身存在的作用域,而不是创建了自己的作用域,这里要小心,从其他语言转来的程序员往往容易犯错。比如

i = 0for i in range(5):    passprint(i)

这里运行结果是打印4而非0。

29e4fb8fce38ba754a005a17eafcd66d.png 4705551134ed8c69eacb26add56eed42.png

听说关注我们的人 都升职加薪啦

你要做的

无非是

长按关注

ad236a7fec3c123f204a85da6acb9205.gif
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值