Python 变量作用域 LEGB (下)—— Enclosing function locals
Posted yvivid
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python 变量作用域 LEGB (下)—— Enclosing function locals相关的知识,希望对你有一定的参考价值。
上篇:Python 变量作用域 LEGB (上)—— Local,Global,Builtin
https://www.cnblogs.com/yvivid/p/python_LEGB_1.html
下篇 没想到 拖这么久,距离上篇完成 都一年多了。
一、闭包常规形态下的 locals作用域
典型的闭包 如下:
def outer(x = 3): def inner(y): print("yvivid\'s test") print("Locals =", locals()) print("Globals =", globals())
return x+y return inner
运行结果如下:
>>> Enclose_Func = outer(73) >>> Enclose_Func(10) yvivid\'s test
Locals = {\'y\': 10, \'x\': 73}
Globals = {\'__name__\': \'__main__\', \'__doc__\': None, \'__package__\': None,
\'__loader__\': <class \'_frozen_importlib.BuiltinImporter\'>,
\'__spec__\': None, \'__annotations__\': {}, \'__builtins__\': <module \'builtins\' (built-in)>,
\'outer\': <function outer at 0x0000018AFDB0CD90>,
\'Enclose_Func\': <function outer.<locals>.inner at 0x0000018AFB091EA0>}
83
可以看到,在 闭包内查看 locals() 时,可以看到 x 和 y。
为了进一步看,x 和 y 是否变化,yvivid将代码变更为如下:
def outer(x = 3): def inner(y): print("yvivid\'s test") print("Locals =", locals()) print("Globals =", globals()) print(id(x), id(y)) return x + y return inner
即,仅增加了 id 的判定。考虑到 python 数字引用机制,使用大于255的数字进行测试。
运行结果如下:
>>> Enclose_Func = outer(500) >>> Enclose_Func(322) yvivid\'s test Locals = {\'y\': 322, \'x\': 500} Globals = {\'__name__\': \'__main__\', \'__doc__\': None, \'__package__\': None,
\'__loader__\': <class \'_frozen_importlib.BuiltinImporter\'>,
\'__spec__\': None, \'__annotations__\': {}, \'__builtins__\': <module \'builtins\' (built-in)>,
\'outer\': <function outer at 0x0000021A09E8CD90>,
\'Enclose_Func\': <function outer.<locals>.inner at 0x0000021A09E86158>} 2310858531312 2310858531600
822
>>> Enclose_Func(322)
yvivid\'s test
Locals = {\'y\': 322, \'x\': 500}
Globals = {\'__name__\': \'__main__\', \'__doc__\': None, \'__package__\': None,
\'__loader__\': <class \'_frozen_importlib.BuiltinImporter\'>,
\'__spec__\': None, \'__annotations__\': {}, \'__builtins__\': <module \'builtins\' (built-in)>,
\'outer\': <function outer at 0x0000021A09E8CD90>,
\'Enclose_Func\': <function outer.<locals>.inner at 0x0000021A09E86158>}
2310858531312 2310858531920
822
可以看到 运行两次,其中 id(y) 是不变更的,而 id(x) 发生了变更,因此 每次 x 是作为形参传入的。而 y 是在 Enclose_Func = outer(500) 时 确定的。
二、闭包特殊形态下的 locals作用域
在 Python 中 部分特殊的 闭包形式。
1、列表推导
>>> [ \'Locals =\' + repr(locals()) for i in range(4)]
["Locals ={\'i\': 0, \'.0\': <range_iterator object at 0x000002C2563CE330>}",
"Locals ={\'i\': 1, \'.0\': <range_iterator object at 0x000002C2563CE330>}",
"Locals ={\'i\': 2, \'.0\': <range_iterator object at 0x000002C2563CE330>}",
"Locals ={\'i\': 3, \'.0\': <range_iterator object at 0x000002C2563CE330>}"]
>>> print("Globals =", globals())
\'Globals =\', {\'__name__\': \'__main__\', \'__doc__\': None, \'__package__\': None,
\'__loader__\': <class \'_frozen_importlib.BuiltinImporter\'>,
\'__spec__\': None, \'__annotations__\': {},
\'__builtins__\': <module \'builtins\' (built-in)>}
>>> i
Traceback (most recent call last):
File "<pyshell#99>", line 1, in <module>
i
NameError: name \'i\' is not defined
可以看到 在yvivid做的 列表推导测试中,globals() 中 是看不到 列表推导中 变量 i 的。
这个和 for 循环有很大的不同。
2、生成器
yvivid_generator = (\'Locals =\' + repr(locals()) for i in range(4))
3、集合推导
yvivid_set = {\'Locals =\' + repr(locals()) for i in range(4)}
-------
A、代码 都基于 Python 3.6 环境。
B、参考书籍 《Python学习手册(第四版)》
【原创文档,引用请声明出处,yvivid】https://www.cnblogs.com/yvivid/p/python_LEGB_2.html
以上是关于Python 变量作用域 LEGB (下)—— Enclosing function locals的主要内容,如果未能解决你的问题,请参考以下文章