参考: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