Python的eval函数详解

目录

      • 原文链接
      • eval()函数
        • 函数原型:
          • 参数
          • 注意
        • 参数使用实例:
          • 省略 globals,locals 参数
          • globals指定的情况下
          • locals指定的情况下
        • 实际使用实例
          • 例一:
          • 示例二:
          • 示例三:
          • 示例四:

原文链接

eval()函数

函数原型:

eval(expression,globals = Nonelocals = None
参数
  • expression:这个参数是一个字符串,python会使用globals字典和locals字典作为全局和局部的命名空间,将expression当做一个python表达式(从技术上讲,是一个条件列表)进行解析和计算
  • globals:这个参数管控的是一个全局的命名空间,也就是我们在计算表达式的时候可以使用全局的命名空间中的函数,如果这个参数被提供了,并且没有提供自定义的__builtins__,那么会将当前环境中的__builtins__拷贝到自己提供的globals里,然后才会进行计算。关于__builtins__,它是python的内建模块,也就是python自带的模块,不需要我们import就可以使用的,例如我们平时使用的int、str、abs等都在这个模块中。如果globals没有被提供,则使用python的全局命名空间。
  • locals:这个参数管控的是一个局部的命名空间,和globals类似,不过当它和globals中有重复的部分时,locals里的定义会覆盖掉globals中的,也就是当globals和locals中有冲突的部分时,locals说了算,它有决定权,以它的为准。如果locals没有被 提供的话,则默认为globals。
注意
  • eval函数也可以被用来执行任意的代码对象(如那些由compile()创建的对象)。在这种情况下,expression参数是一个代码对象而不是一个字符串。如果代码对象已经被‘exec‘编译为模式参数,eavl()的返回值是None。

参数使用实例:

省略 globals,locals 参数
a = 10
print(eval("a+10"))
# 输出:20
  • 分析:后两个参数省略了,所以eval中的a是前面的10。对于eval,它会将第一个expression字符串参数的引号去掉,然后对引号中的式子进行解析和计算。
globals指定的情况下
a = 10
g = {'a':5}
print(eval('a+10',g))
# 输出:15
  • 分析:在这次的代码中,我们在 eval中提供了globals参数,这时候eval的作用域就是g指定的这个字典了,也就是外面的a=10被屏蔽掉了,eval是看不见的,所以使用了a为5的值。
locals指定的情况下
a = 10
b = 20
c = 30
g = {'a':1,'b':2}
l = {'b':200,'c':3}
print(eval("a+b+c",g,l))
# 输出:204
  • 分析:此次执行的结果中,a是1,b是200,c是3。我们首先来看一下,对于a为1我们是没有疑问的,因为在上个例子中已经说了,g会屏蔽程序中的全局变量的,而这里最主要的是为什么b是100呢?还记得我们在参数介绍的时候说过,当locals和globals起冲突时,locals是起决定作用的

实际使用实例

例一:
s="abck"
print(eval(s))

# 输出:NameError: name 'abck' is not defined
  • 分析:字符串s并不满足表达式的要求。当eval剥去了"abck"的外面的引号的时候,它会对它进行解析,然后满足要求后进行计算,然后它解析到的是abcd,请注意,程序报出的错误是NameError,也就是说,当它解析到这个表达式是不可以计算后,它就会查找它是不是一个变量的名字,如果是一个变量的名字,那么它会输出这个变量的内容,否则就会产生这种报错。
s="abck"
print(eval('s'))
#输出:abck
  • 分析:eval首先将‘s’的引号剥去,然后得到的是s,显然这个是不可以进行计算的,那么它就开始查找s是否是一个变量的名字,然后它一查找,果然s是一个字符串,所以程序输出了s中的内容
示例二:
s='"sas"'
print(eval(s))
# 输出:sas
  • 分析:eval首先去除单引号,eval在执行的时候是只会去除同种类型的引号的,对于单引号和双引号它是加以区分的。eval去除单引号后得到了“sas”,这个时候程序解析到它是一个字符串,不可以计算,就输出了它。那么不禁想问,为什么上个例子中s="abck"会不行呢,这里面我们就可以看出区别了,一个是有引号括起来的,一个是没有的,引号括起来代表字符串,虽然不可以求值,但是是有意义的,可以进行输出,而没引号的便无法判断“身份”了,只能当做变量名进行解析,而abck并不是一个变量名,所以就报错了。

  • 同理:

s='["a","b","c"]'
print(eval(s))
# 输出:['a', 'b', 'c']
示例三:
a = 10
b = 20
c = 30
s = '[a,b,c]'
print(eval(s))
# 输出:[10, 20, 30]
  • 分析:eval检查到列表的‘[’‘]’符号时,是会对里面的元素进行解析的,这里a、b、c显然不是具体的数据,便去查找它们是否是变量名,然后确认是变量名后,用它们的内容替换掉它。
示例四:
s = 'abs(10)'
print(eval(s))
# 输出:10
  • 分析:对于这个程序,我们举的是一个满足计算的一个表达式,当eval剥去s的引号后,得到abs(10),然后它会对进行解析,这个解析我们前面介绍eval的时候说过,它会使用globals的内建模块__builtins__进行解析的,在这个内建模块中是有abs这个函数的,所以对abs(10)进行了计算。

  • 关于__builtins__模块中有哪些东西 ,我们可以这样查看

print(dir(__builtins__))

你可能感兴趣的:(Python)