python eval()
eval(expression, globals= None, locals= None)
--官方文檔中的解釋:
將字符串str當成有效的表達式子來求值並返回計算結果。
globals(全局)和locals(局部)參數是可選的,如果提供了globals參數,那么它必須是dictionary類型;
如果提供了locals參數,那么它可以是任意的map對象。
python查找變量的順序:局部--> 全局--> 內置
三個參數的使用:
1、在前兩個參數省略的情況下,eval在當前的作用域執行:
a=10; print(eval("a+1"))
執行結果為:11
在這種情況下,后兩個參數省略了,所以eval中的a是前面的10。對於eval,它會將第一個expression字符串參數的引號去掉,然后對引號中的式子進行解析和計算。
2、在globals指定的情況下:
a=10; g={'a':4} print(eval("a+1",g))
執行結果為:5
這里面可能有點繞啊,初學者得理理清楚。在這次的代碼中,我們在 eval中提供了globals參數,這時候eval的作用域就是g指定的這個字典了,也就是外面的a=10被屏蔽掉了,eval是看不見的,所以使用了a為4的值。
3、在 locals指定的情況下 :
a=10 b=20 c=30 g={'a':6,'b':8} t={'b':100,'c':10} print(eval('a+b+c',g,t))
執行的結果為:116
這里面就更有點繞人了,此次執行的結果中,a是6,b是100,c是10。我們首先來看一下,對於a為6我們是沒有疑問的,因為在上個例子中已經說了,g會屏蔽程序中的全局變量的,而這里最主要的是為什么b是100呢?還記得我們在參數介紹的時候說過,當locals和globals起沖突時,locals是起決定作用的,這在很多編程語言里都是一樣的,是作用域的覆蓋問題,當前指定的小的作用域會覆蓋以前大的作用域,這可以理解為一張小的紙蓋在了一張大的紙上,紙是透明的,上面寫的東西是不透明的,而它們重合的地方就可以理解成兩個作用域沖突的地方,自然是小的顯現出來了。
eval()的用法:
可以把list, tuple, dict和string相互轉化。例子:
#字符串轉數字
a = '2'
b = '3'
c = eval(a + b)
c
Out : 5
type(c)
Out : int
#字符串轉列表 a = "[[1,2], [3,4], [5,6], [7,8], [9,0]]" b = eval(a) b Out[3]: [[1, 2], [3, 4], [5, 6], [7, 8], [9, 0]] type(b) Out[4]: list #字符串轉字典 a = "{1: 'a', 2: 'b'}" b = eval(a) b Out[7]: {1: 'a', 2: 'b'} type(b) Out[8]: dict #字符串轉元組 a = "([1,2], [3,4], [5,6], [7,8], (9,0))" b = eval(a) b Out[11]: ([1, 2], [3, 4], [5, 6], [7, 8], (9, 0))
需要注意的是,eval()函數的安全性問題
想一想這種使用環境:需要用戶輸入一個表達式,並求值。
如果用戶惡意輸入,例如:
__import__('os').system('dir')
那么eval()之后,你會發現,當前目錄文件都會展現在用戶前面。
那么繼續輸入:
open('文件名').read()
代碼都給人看了。獲取完畢,一條刪除命令,文件消失。