python - 如何在Python3中使用exec根据字典将列表分配给变量?

标签 python python-3.x python-2.7 exec local-variables

我想将列表分配给变量,而listvariable都存储在字典measurements中。这是带有较少变量的 测量 的 Python 2 版本:

measurements = {'tg': [8.184e+16, 8.345e+16, 8.045e+16, 8.520e+16, 8.322e+16, 7.622e+16, 4.305e+16, 2.203e+16]}

def f():
    for key,val in measurements.items():
        exec(key + ' = val') in globals(),locals()
    print (tg)
f()

但是,正如 another question 中提到的,它不适合Python 3。 如果我这样写代码:

measurements = {'tg': [8.184e+16, 8.345e+16, 8.045e+16, 8.520e+16, 8.322e+16, 7.622e+16, 4.305e+16,
 2.203e+16]}

def f():
    for key,val in measurements.items():
        ldict = {}
        exec(key + ' = val', globals(),ldict)
        key = ldict[key]
        # exec(key + ' = val') in globals(),locals()
    print (tg)
f()

我收到此错误:NameError:名称“val”未定义

最佳答案

ldict = {} 技巧创建一个替代本地命名空间以在 exec 内部使用。这很有用,因为 locals() 返回的字典不会像 Python 2 中那样写入实际的本地变量。

但是该替代命名空间 {} 是空的。它不包含您的 locals(),因此它没有 val 。尝试使用 ldict = {**locals()} 将本地变量的内容复制到替代本地变量 ldict

<小时/>

请记住,您必须从 ldict 中读取 exec 创建的所有“局部变量”。因此,print(tg) 也不起作用,因为它仅被分配到替代本地命名空间之一。您可能不想每次循环都创建一个新的。只需提前创建一个 .update() 即可。

def f():
    ldict = {}
    for key,val in measurements.items():
        ldict.update(locals())
        exec(key + ' = val', globals(),ldict)
        key = ldict[key]
        # exec(key + ' = val') in globals(),locals()
    print (ldict['tg'])
<小时/>

Python3 中的编译器必须提前知道局部变量的数量和名称,以优化性能。 (这不适用于 globals(),它们仍然会直写。)

如果你提前知道它们,你可以直接从它们中分配,例如

tg = ldict['tg']
print(tg)

如果您需要多个字典,您可以将字典解压为本地字典,例如

a, b, c = (ldict[key] for key in ['a', 'b', 'c'])

或者您可以将整个字典转储到一个简单的命名空间中,并使用 . 而不是 [] 访问它们。

from types import SimpleNamespace

# ...

ns = SimpleNamespace(**ldict)
print(ns.tg)

您还可以exec任何需要新局部变量的代码,因为您可以为exec提供ldict命名空间。

exec("print(tg)", globals(), ldcit)
<小时/>

我知道您的示例代码可能比原始代码有所简化,但它似乎根本不需要exec。除非您绝对需要,否则通常认为使用 exec 是不好的形式,因为它会混淆静态分析工具,并且在运行时编译字符串很慢,尤其是在这样的循环中重复时。

如果必须使用 exec,最好将循环放在 exec 字符串内(使用三引号),而不是在循环内调用 exec。这样,字符串只需编译一次,而不是每次循环。

关于python - 如何在Python3中使用exec根据字典将列表分配给变量?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52751674/

相关文章:

python - Odoo - 防止按钮关闭向导

Python 3.4 多重处理,代码不会超过循环(包含队列)

python - 如何登录 Appengine 中的任意用户以使用 Drive SDK?

python - Pandas - 数据框与一系列值的合并

python - numpy 中检查向量是否对齐或方向相反的最快方法(截断的 SVD 后处理)

python-3.x - PYVISA:如何传输二进制 block 数据,以便图片正确格式化并保存到我的电脑上?

python-3.x - 如何使用 scikit 图像在 python 中的图像上裁剪一个圆的扇区

python - 如何获取字典以保存新添加的项目以供下次运行?

python - 动画 GIF 仅在第一帧上是透明的 (Python PIL)

python - 石头剪刀布不打印结果