參考:https://docs.python.org/2/library/functions.html#evalhtml
eval(expression[, globals[, locals]])python
The arguments are a Unicode or Latin-1 encoded string and optional globals and locals. If provided, globals must be a dictionary. If provided, locals can be any mapping object.express
Changed in version 2.4: formerly locals was required to be a dictionary.安全
The expression argument is parsed and evaluated as a Python expression (technically speaking, a condition list) using the globalsand locals dictionaries as global and local namespace. If the globals dictionary is present and lacks ‘__builtins__’, the current globals are copied into globals before expression is parsed. This means that expression normally has full access to the standard__builtin__ module and restricted environments are propagated. If the locals dictionary is omitted it defaults to the globalsdictionary. If both dictionaries are omitted, the expression is executed in the environment where eval() is called. The return value is the result of the evaluated expression. Syntax errors are reported as exceptions. Example:app
>>> x = 1
>>> print eval('x+1')
2
This function can also be used to execute arbitrary code objects (such as those created by compile()). In this case pass a code object instead of a string. If the code object has been compiled with 'exec' as the mode argument, eval()‘s return value will beNone.ide
Hints: dynamic execution of statements is supported by the exec statement. Execution of statements from a file is supported by theexecfile() function. The globals() and locals() functions returns the current global and local dictionary, respectively, which may be useful to pass around for use by eval() or execfile().函數
See ast.literal_eval() for a function that can safely evaluate strings with expressions containing only literals.ui
1 globals = {'x': 7,
2 'y': 10,
3 'birds': ['Parrot', 'Swallow', 'Albatross']
4 }
5 locals = { }
6
7 # 將上邊的字典做爲全局和局部名稱空間
8 a = eval("3*x + 4*y", globals, locals)
轉:表達式與語句 局部變量與全局變量 exec與eval
Python有時須要動態的創造Python代碼,而後將其做爲語句執行 或 做爲表達式計算。this
exec用於執行存儲在字符串中的Python代碼。lua
一、 語句與表達式的區別:表達式是 某事,語句是 作某事(即告訴計算機作什麼)。
好比2*2是4,而print 2*2是打印4。上述兩句代碼在交互式解釋器中執行的結果是同樣的,是由於解釋器老是把全部表達式的值打印出來而已。而在程序中編寫相似2*2這樣的表達式並不會打印顯示什麼,編寫print 2*2則會打印4。
語句與表達式的區別在賦值時更明顯,由於語句不是表達式,因此沒有值。如在交互式解釋器中輸入 x=2則不會打印任何東西,馬上出現新的提示符。雖然什麼也沒顯現,可是有些東西已經發生變化如x的值如今變爲3.這也是語句特性的通常定義:它們改變了事物。好比,賦值語句改變了變量,print語句改變了屏幕顯示的內容。
二、 命名空間(做用域) 全局變量和局部變量
除了全局做用域外,每一個函數會都會建立一個新的做用域。變量分爲全局變量和局部變量,函數內的變量稱爲局部變量只在局部命名空間中起做用。
在函數內部讀取全局變量通常來講不是問題,直接訪問便可。可是,若是局部變量名或者參數的名字與全局變量名相同的話,就不能直接訪問了,由於全局變量被局部變量給屏蔽了。若是確實須要的話,可使用globals函數獲取被屏蔽的全局變量值。(globals返回全局變量的字典,locals返回局部變量的值)。例如:有一個名爲parameter的全局變量,那麼在combine(parameter)函數內部訪問全局變量時,由於與參數重名,必須使用globals()['parameter']獲取。代碼以下:
1 |
def combine(parameter): |
2 |
print parameter + globals ()[ 'parameter' ] |
3 |
4 |
#函數調用 |
5 |
parameter = "hello" |
6 |
combine( "berry" ) |
上面講的是再函數內部讀取全局變量的方法,不包括修改。若是要在函數內部修改全局變量,須要告知修改的值是全局變量,由於在函數內部將值賦予一個變量那麼變量自動成爲局部變量。經過global關鍵字來告訴Python函數內一個須要修改的變量是一個全局變量。代碼以下:
1 |
x = 1 |
2 |
def change_global(n): |
3 |
global x |
4 |
x = x + 1 |
三、執行字符串的語句 exec
如輸入exec "print 'hello'"會打印出hello。(注意:Python 3.0中,exec是一個函數不是一個語句了,所以使用exec('字符串語句')的方式來調用)。exec執行字符串語句存在安全風險,由於exec可能會干擾命名空間,即改變不該該變的變量。例如:
從上面的例子能夠看出,exec干擾了命名空間,改變了sqrt的值,使其不是一個函數而變成1了。因而可知,若是對exec不加限制就會存在安全風險。下面是改進措施。
措施:經過增長 in <scope>來實現,其中的<scope>是一個字典,該字典起到放置代碼字符串命名空間的做用。這樣exec執行的代碼只會在<scope>表明的命名空間中起做用。如:
從上面代碼中能夠看到,exec語句在scope命名空間中執行,不會影響到如今命名空間的sqrt。scope雖然充當命名空間的做用,但實質還是一個字典,因此若是想知道scope命名空間中有多少變量時,可經過len(scope)得到,可經過scope.key()得到scope命名空間的全部變量。
四、eval 會計算字符串形式的Python表達式,並返回結果的值。
exec語句不會返回任何對象。而eval會返回表達式的值。下面的代碼能夠建立一個Python計算器:
1 |
#Python計算器 |
2 |
print eval ( raw_input ( "Please input an arithmetic expression:" )) |
上面代碼解釋,上面代碼中eval內部如今還不是字符串,首先執行raw_input()函數,raw_input()返回你輸入的求值字符串,如今eval函數內部就是求值字符串了,就能夠用eval進行字符串的求值了。如輸入:4*5+6,那麼raw_input就會返回「4*5+6」,eval求值後爲26.
要注意上面代碼與下面代碼的區別:
1 |
print eval ( 'raw_input("Please input an arithmetic expression:")' ) |
在這個代碼中,與Python計算器代碼不一樣的是,eval函數內直接就是字符串,那麼直接對字符串求值,可是字符串中是raw_input表達式,raw_input表達式將用戶的輸入轉換爲字符串,因此若是輸入4+5的話會返回"4+5"。注意:raw_input('xxxxx')是一個表達式,表達式的值就是用戶輸入。 可能疑惑的是代碼:exec('raw_input("Please input an arithmetic expression:")')不會報錯,由於ecec也能夠用於表達式,只是什麼效果也沒達到而已(既不返回值,也沒幹事情)。
跟exec同樣,eval也可使用命名空間。由於儘管表達式通常不會給變量從新賦值,可是表達式能夠經過調用函數來達到給全局變量賦值的目的。例如執行下面代碼後,全局變量x的值會被從新賦值爲2:
1 |
x = 1 |
2 |
def inc_x(): |
3 |
global x |
4 |
x = x + 1 |
5 |
eval ( "inc_x()" ) |
6 |
print x |
從上面的代碼能夠看出eval函數也是不安全的,必須使用命名空間。事實上,能夠爲eval提供兩個命名空間,一個是全局的,另外一個是局部的。全局的必須是字典,局部的能夠是任何形式的映射。
exec和eval的命名空間使用代碼(命名空間能夠不是空的字典,能夠提早爲命名空間提供一些值):
1 |
scope = {} |
2 |
scope[ 'x' ] = 1 |
3 |
scope[ 'y' ] = 2 |
4 |
print eval ( 'x+y' ,scope) |
1 |
scope = {} |
2 |
exec "x=2" in scope |
3 |
eval ( "x*x" ,scope) |
參考:http://my.oschina.net/duhaizhang/blog/66048