栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

在python 3中的函数中创建动态命名的变量/在python 3中了解exec / eval / locals

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

在python 3中的函数中创建动态命名的变量/在python 3中了解exec / eval / locals

当您不确定某个东西为什么能在Python中正常工作时,它通常可以帮助将您困惑的行为放入函数中,然后使用该

dis
模块将其从Python字节码中分解出来。

让我们从一个简单的代码版本开始:

def foo():    exec("K = 89")    print(K)

如果运行

foo()
,您将得到与更复杂的函数相同的异常:

>>> foo()Traceback (most recent call last):  File "<pyshell#167>", line 1, in <module>    foo()  File "<pyshell#166>", line 3, in foo    print(K)NameError: name 'K' is not defined

让我们分解一下,看看为什么:

>>> import dis>>> dis.dis(foo)  20 LOAD_GLOBAL   0 (exec)   3 LOAD_ConST    1 ('K = 89')   6 CALL_FUNCTION 1 (1 positional, 0 keyword pair)   9 POP_TOP  3          10 LOAD_GLOBAL   1 (print)  13 LOAD_GLOBAL   2 (K)  16 CALL_FUNCTION 1 (1 positional, 0 keyword pair)  19 POP_TOP  20 LOAD_ConST    0 (None)  23 RETURN_VALUE

您需要注意的操作是标为“
13”的操作。这是编译器

K
在函数的最后一行(
print(K)
)中查找的地方。它使用的
LOAD_GLOBAL
操作码失败,因为“
K”不是全局变量名称,而是它在我们的
locals()
字典中的值(由
exec
调用添加)。

如果我们说服编译器将其

K
视为局部变量(在运行之前为其提供值
exec
),那么它将知道不寻找不存在的全局变量怎么办?

def bar():    K = None    exec("K = 89")    print(K)

如果运行该函数,将不会出现错误,但不会输出期望值:

>>> bar()None

让我们分解一下原因:

>>> dis.dis(bar)  20 LOAD_ConST    0 (None)   3 STORE_FAST    0 (K)  36 LOAD_GLOBAL   0 (exec)   9 LOAD_ConST    1 ('K = 89')  12 CALL_FUNCTION 1 (1 positional, 0 keyword pair)  15 POP_TOP  4          16 LOAD_GLOBAL   1 (print)  19 LOAD_FAST     0 (K)  22 CALL_FUNCTION 1 (1 positional, 0 keyword pair)  25 POP_TOP  26 LOAD_ConST    0 (None)  29 RETURN_VALUE

注意在“ 3”和“
19”处使用的操作码。Python编译器使用

STORE_FAST
LOAD_FAST
将局部变量的值
K
放入插槽0,然后将其取回。使用编号的插槽比从像这样的字典中插入和获取值的速度要快得多
locals()
,这就是Python编译器为函数中的所有局部变量访问而这样做的原因。您不能通过修改返回的字典来覆盖插槽中的局部变量
locals()
exec
如果您不将其传递给它的命名空间的字典,也一样)。

确实,让我们尝试函数的第三个版本,

locals
当我们将
K
其定义为常规局部变量时,可以再次浏览:

def baz():    K = None    exec("K = 89")    print(locals())

89
这次您也不会在输出中看到!

>>> baz(){"K": None}

函数文档中解释了您看到旧

K
值的原因:
locals()

更新并返回代表当前本地符号表的字典。

该语句

K
未更改存储本地变量值的插槽,该
exec
语句仅修改
locals()
字典。
locals()
再次调用时,Python使用插槽中的值“更新”字典,用替换存储在其中的值
exec

这就是为什么文档继续说:

注意: 此字典的内容不得修改;更改可能不会影响解释器使用的局部变量和自由变量的值。

您的

exec
呼叫正在修改
locals()
字典,并且您发现以后的代码并不总是看到其更改。



转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/617502.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号