python eval函数

参考:https://docs.python.org/2/library/functions.html#eval

eval(expression[globals[locals]])

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.

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:

>>>
>>> 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.

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.

 

globals = {‘x‘: 7, 
‘y‘: 10, 
‘birds‘: [‘Parrot‘, ‘Swallow‘, ‘Albatross‘] 
4     } 
locals = { } 
# 将上边的字典作为全局和局部名称空间 
a = eval("3*x + 4*y", globals, locals) 
转:表达式与语句 局部变量与全局变量 exec与eval

  Python有时需要动态的创造Python代码,然后将其作为语句执行  或  作为表达式计算。

              exec用于执行存储在字符串中的Python代码。

             1、 语句与表达式的区别:表达式是 某事,语句是 做某事(即告诉计算机做什么)。

              比如2*2是4,而print 2*2是打印4。上述两句代码在交互式解释器中执行的结果是一样的,是因为解释器总是把所有表达式的值打印出来而已。而在程序中编写类似2*2这样的表达式并不会打印显示什么,编写print 2*2则会打印4。

              语句与表达式的区别在赋值时更明显,因为语句不是表达式,所以没有值。如在交互式解释器中输入 x=2则不会打印任何东西,立刻出现新的提示符。虽然什么也没显现,但是有些东西已经发生变化如x的值现在变为3.这也是语句特性的一般定义:它们改变了事物。比如,赋值语句改变了变量,print语句改变了屏幕显示的内容

python eval函数

  2、 命名空间(作用域) 全局变量和局部变量

             除了全局作用域外,每个函数会都会创建一个新的作用域。变量分为全局变量和局部变量,函数内的变量称为局部变量只在局部命名空间中起作用。

            在函数内部读取全局变量一般来说不是问题,直接访问即可。但是,如果局部变量名或者参数的名字与全局变量名相同的话,就不能直接访问了,因为全局变量被局部变量给屏蔽了。如果确实需要的话,可以使用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

 

              3、执行字符串的语句  exec

               如输入exec "print  ‘hello‘"会打印出hello。(注意:Python 3.0中,exec是一个函数不是一个语句了,因此使用exec(‘字符串语句‘)的方式来调用)。exec执行字符串语句存在安全风险,因为exec可能会干扰命名空间,即改变不应该变的变量。例如:

python eval函数

                   从上面的例子可以看出,exec干扰了命名空间,改变了sqrt的值,使其不是一个函数而变成1了。由此可见,如果对exec不加限制就会存在安全风险。下面是改进措施。

               措施:通过增加 in <scope>来实现,其中的<scope>是一个字典,该字典起到放置代码字符串命名空间的作用。这样exec执行的代码只会在<scope>代表的命名空间中起作用。如:

python eval函数

   从上面代码中可以看到,exec语句在scope命名空间中执行,不会影响到现在命名空间的sqrt。scope虽然充当命名空间的作用,但实质仍是一个字典,所以如果想知道scope命名空间中有多少变量时,可通过len(scope)获得,可通过scope.key()获得scope命名空间的所有变量。

                4、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

 

python eval函数,布布扣,bubuko.com

python eval函数

上一篇:java学习笔记(十八)——Java DTO


下一篇:Linux 的多线程编程的高效开发经验