我想为变量分配列表,而list
和variable
都存储在字典measurements
中。这是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: name 'val' is not defined
答案 0 :(得分:1)
ldict = {}
技巧创建了一个替代的本地命名空间,供在exec
内部使用。这很有用,因为locals()
返回的字典不会像Python 2中那样直接写入您的实际本地语言。
但是替代名称空间{}
为空。它不包含您的locals()
,因此其中没有val
。尝试使用ldict = {**locals()}
代替将您的本地人的内容复制到替代本地人ldict
。
请记住,您必须从exec读取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调用。这样一来,字符串只需要编译一次,而不必为每个循环编译一次。
答案 1 :(得分:1)
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('{} = {}'.format(key, val))
print (tg)
local = locals()
for key in measurements.keys():
print 'Key: ', key, ', Value: ', local[key]
f()
python3:
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('global {};{} = {}'.format(key, key, val))
print ('tg: ', tg)
vars = globals()
for key in measurements.keys():
print ('Key: ', key, ', Value: ', vars[key])
f()
输出:
[8.184e+16, 8.345e+16, 8.045e+16, 8.52e+16, 8.322e+16, 7.622e+16, 4.305e+16, 2.203e+16]
Key: tg , Value: [8.184e+16, 8.345e+16, 8.045e+16, 8.52e+16, 8.322e+16, 7.622e+16, 4.305e+16, 2.203e+16]
答案 2 :(得分:0)
几年后,但我意识到您可以(ab)使用在类声明中创建的临时名称空间来获取函数内部的write-through locals()名称空间。这使您可以直接翻译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():
class _:
for key,val in measurements.items():
exec(key + ' = val', globals(), locals())
print (tg)
f()