Python中的eval()函數eval(expression, globals=None, locals=None) 官方文檔中的解釋是,將字符串str當成有效的表達式來求值並返回計算結果。globals和locals參數是可選的,如果提供了globals參數,那么它必須是dictionary類型;如果提供了locals參數,那么它可以是任意的map對象。
example:
a=1
g={'a':20}
eval("a+1",g)
返回21
python是用命名空間來記錄變量的軌跡的,命名空間是一個dictionary,鍵是變量名,值是變量值。
當一行代碼要使用變量 x 的值時,Python 會到所有可用的名字空間去查找變量,按照如下順序:
1)局部名字空間 - 特指當前函數或類的方法。如果函數定義了一個局部變量 x, 或一個參數 x,Python 將使用它,然后停止搜索。
2)全局名字空間 - 特指當前的模塊。如果模塊定義了一個名為 x 的變量,函數或類,Python 將使用它然后停止搜索。
3)內置名字空間 - 對每個模塊都是全局的。作為最后的嘗試,Python 將假設 x 是內置函數或變量。
python的全局名字空間存儲在一個叫globals()的dict對象中;局部名字空間存儲在一個叫locals()的dict對象中。我們可以用print (locals())來查看該函數體內的所有變量名和變量值。
eval()使用原因:
1)在編譯語言里要動態地產生代碼,基本上是不可能的,但動態語言是可以,意味着軟件已經部署到服務器上了,但只要作很少的更改,只好直接修改這部分的代碼,就可立即實現變化,不用整個軟件重新加載。
2)在machin learning里根據用戶使用這個軟件頻率,以及方式,可動態地修改代碼,適應用戶的變化。
#test eval() and locals()
x = 1
y = 1
num1 = eval("x+y")
print (num1)
def g():
x = 2
y = 2
num3 = eval("x+y")
print (num3)
num2 = eval("x+y",globals())
#num2 = eval("x+y",globals(),locals())
print (num2)
g()
print locals()["x"]
print locals()["y"]
print globals()["x"]
print globals()["y"]
num1的值是2;num3的值也很好理解,是4;num2的值呢?由於提供了globals()參數,那么首先應當找全局的x和y值,也就是都為1,那么顯而易見,num2的值也是2。如果注釋掉該句,執行下面一句呢?根據第3)點可知,結果為4
locals()對象的值不能修改,globals()對象的值可以修改
#test globals() and locals()
z=0
def f():
z = 1
print (locals())
locals()["z"] = 2
print (locals())
f()
globals()["z"] = 2
print (z)
可以得出,兩個print (locals())的結果是一樣的,說明沒有修改成功。而print (z)的值是2,說明修改成功了
eval有安全性問題,比如用戶惡意輸入就會獲得當前目錄文件
eval("__import__('os').system('dir')")
>>> import os
>>> 'os' in globals()
True
>>> os.system('whoami')
ap\zhail
0
怎么避免安全問題?
1.自行寫檢查函數;
2.使用ast.literal_eval
參考如下網址:
https://docs.python.org/2/library/ast.html
http://python.jobbole.com/82770/
http://code.activestate.com/recipes/496746-restricted-safe-/
