2017-08-15 37 views
0

我想用字典中的变量计算一个公式。例如:如何在exec或eval中使用无效变量名称?

d = {'a': 1} 
exec('b=a+1', globals(), d) # d => { 'a': 1, 'b': 2 } 

由于字典的数据源是从Python的外部(例如,JSON/YAML),词典的键名可以是像Python的变量名无效。所以下面的代码:

d = {':a': 1} 
exec('b=:a+1', globals(), d) # expected d => { ':a': 1, 'b': 2} 

抛出错误:

File "<string>", line 1 
b=:a 
^
SyntaxError: invalid syntax 

你有什么想法使用无效的变量在EXEC或EVAL?

+0

使用正则表达式,并去掉无效字符和领先的数字。 –

+0

'exec'和'eval'要求输入是有效的Python。为什么你首先得到':a + 1'这样的东西?如果输入是“这是一个无效表达式+ 3”,那么你打算怎么做? – Barmar

+0

你有一个逻辑问题。您无法解析和计算完全任意的输入数据。必须有*一些*可变的命名规则,你必须知道它们是什么。如果变量名在这些规则下有效,但在Python中无效,则必须在调用exec/eval之前将其转换。您用于名称转换的算法必须避免生成恰好与已使用的其他名称匹配的新名称。 –

回答

0

[基于替代的方法]

这个怎么样?我确认这个工作正确。

但是这不能处理像“:b =:a + 1”这样的新的无效变量分配。

d = {':a': 1} 
expression = 'b=:a+1' 

def exec2(expression, d): 

    d2 = {} 
    keymap={} 
    for idx, (k, v) in enumerate(d.items()): 
     k2 = "_" + str(idx) 
     d2[k2] = v 
     keymap[k2] = k 

     expression = expression.replace(k, k2) 

    # d2 => {'_0': 1} 
    # expression => b=_0+1 

    exec(expression, globals(), d2) 

    for k2, v in d2.items(): 
     if k2 in keymap: 
      k = keymap[k2] 
      d[k] = v 
     else: 
      d[k2] = v 
    # d => {':a': 1, 'b': 2} 
    return d 
0

[使用表达式d [k]的朴素方法]如果我们能够执行使用“d [k]的”在表达它的作者,那么我们就可以处理此无需更换。

该方法还可以处理新的无效变量分配,如“:b =:a + 1”。

但在这种方法中,作者必须意识到这种逃避格式...

def exec3(expression, d): 
    exec(expression, globals(), d) 
    return d 

d = {':a': 1} 
expression = 'b= d[":a"] + 1' 
exec3(expression, d) # d => {':a': 1, 'b': 2} 

d = {':a': 1} 
expression = 'd[":b"] = d[":a"] + 1' 
exec3(expression, d) # d => {':a': 1, ':b': 2}