2017-08-15 35 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}