python内置函数eval详解 && python内置函数exec详解

python内置函数exec详解

eval函数功能作用

 eval(str) 函数很强大,官方解释:python内置函数 eval 解析字符串并将其当做有效的表达式来求值并返回计算结果。(但是由于eval不对表达式进行检查,因此存在安全漏洞,容易被不法人员利用,官方推荐使用ast.literal_eval来替代eval函数)

eval函数语法

eval(expression[, globals[, locals]])

或者理解为:

eval(expression, globals=None, locals=None, /)

参数:

  • expression 字符串,内容为表达式。
  • globals 字典,默认使用当前作用域的全局命名空间。
  • locals 映射类型对象,默认使用当前作用域的局部命名空间。

返回值:

表达式计算结果。

1、示例代码①:

exp = "3 + 4*5"
print(eval(exp))  # 23

详解:exp是一个字符串,eval能够解析并执行它,eval的功能非常强大,只要表达式是合法的,就能执行。

2、示例代码②:

def test():
    print("执行函数")


exp = "test()"
eval(exp)  # 执行函数

详解:exp的内容是一个表达式,test() 调用执行函数test,eval对这种函数调用的表达式也可以解析并执行。

eval可以视作一种动态执行python代码的方法,在不提供固定编码的前提下,通过生成exp表达式然后用eval执行的方式动态执行python代码。

eval()函数常见用法

1、计算字符串中有效的表达式,并返回结果。

>>> eval('pow(2,2)')
4
>>> eval('2 + 2')
4
>>> eval("n + 4")
85

2、将字符串转成相应的python对象(如list、tuple、dict和string之间的转换)

      将python内存中的数据类型转成其该有的数据类型,而不是json字符串

>>> a = "[[1,2], [3,4], [5,6], [7,8], [9,0]]"
>>> b = eval(a)
>>> b
[[1, 2], [3, 4], [5, 6], [7, 8], [9, 0]]
>>> a = "{1:'xx',2:'yy'}"
>>> c = eval(a)
>>> c
{1: 'xx', 2: 'yy'}
>>> a = "(1,2,3,4)"
>>> d = eval(a)
>>> d
(1, 2, 3, 4)

例外:json格式的字典字符串如果键值对中的值为单字节的话可以使用eval()表达式转换为python数据类型【例如json转dict】

          ①但是如果json格式的字典字符串中的键值对中的值为复杂的数据类型如列表或者列表中嵌套字典则无法将json转换为dict数据

          ②eval(str)当字符串中有null【null的反序列化通过json.load()方法可以转换为None】值,无法将字符串转成相应的对象,会报错。

json_string = """{
  "answerList": [
    {
      "content": "string",
      "questionId": "string",
      "questionIndex": 0,
      "questionTitle": "string",
      "questionType": 0,
      "questionWeight": 0,
      "score": 0,
      "scoreId": "string",
      "scoreName": "string",
      "scoreWeight": 0,
      "selectOptions": [
        {
          "disabledWeight": true,
          "evaluateStatus": 0,
          "optionId": "string",
          "optionTitle": "string",
          "optionWeight": 0
        }
      ],
      "tags": [
        {
          "tagId": "string",
          "tagTitle": "string"
        }
      ]
    }
  ],
  "channel": "string",
  "externalUnionid": "string",
  "key": "string",
  "qaJson": "string",
  "unionid": "string",
  "uuid": "string"
}"""

print(json_string) # 打印json字符串
print(type(json_string)) # 打印json字符串的类型:str

print(eval(json_string)) # 使用eval()表达式把json字符串转换为python数据类型:字典类型--》结果失败,报错

json_dict = json.loads(json_string) # 使用json.loads反序列化方式,将json字符串转换为python数据类型成功
print(type(json_dict)) # 打印转换后的数据类型:dict
print(json_dict) # 打印转换成功后的字典数据

3、将利用反引号转换的字符串再反转回对象

>>> list1 = [1,2,3,4,5]
>>> `list1`
'[1, 2, 3, 4, 5]'
>>> type(`list1`)
<type 'str'>
>>> type(eval(`list1`))
<type 'list'>
>>> a = eval(`list1`)
>>> a
[1, 2, 3, 4, 5]

python内置函数exec详解

exec函数功能作用

python内置函数 exec 函数支持动态执行python代码,传入 exec 函数的object实参可以是字符串,也可以是字节码对象。如果object实参是字符串则会被exec函数编译并执行,如果是字节码对象则会被直接执行。通常exec配合compile函数来使用。

exec函数语法

exec(object[, globals[, locals]])

或者理解为:

exec(object, globals=None, locals=None, /)

参数:

  • object 可以是字符串或者字节码对象。
  • globals 可选参数,如果提供了必须是字典对象,若不提供,则使用当前作用域里的globals。
  • locals 可选参数,任意字典映射对象。

一旦提供了globals 和 locals, 代码执行起来就像嵌入到某个类定义中一样。

示例代码

1、示例代码①:object实参是字符串

exec("print('ok')")  # ok

result = exec("4 + 5")
print(result)  # None

result = exec("print(4 + 5)")  # 9
print(result)  # None

虽然字符串 "4 + 5" 也能被 exec 函数执行,但并没有返回结果,这一点一定要注意。

1、示例代码②:object实参是字节码

>>> exp = "3*3 + 7 + 8"                    
>>> code = compile(exp, '<string>', 'eval')
>>> code
<code object <module> at 0x2b9c88626ed0, file "<string>", line 1>
>>> eval(exp)
24

eval()函数和exec()函数的区别

1、eval() 和 exec() 函数都属于 Python 的内置函数,这两个函数在功能和用法方面都有相似之处。

2、eval() 和 exec() 函数的功能是相似的,都可以执行一个字符串形式的 Python 代码(代码以字符串的形式提供),相当于一个 Python 的解释器。二者不同之处在于,eval() 执行完要返回结果,而 exec() 执行完不返回结果

3、eval() 函数的语法格式为:

eval(expression, globals=None, locals=None, /)

exec() 函数的语法格式如下:

exec(expression, globals=None, locals=None, /)

可以看到,二者的语法格式除了函数名,其他都相同,其中各个参数的具体含义如下:

  • expression:这个参数是一个字符串,代表要执行的语句 。该语句受后面两个字典类型参数 globals 和 locals 的限制,只有在 globals 字典和 locals 字典作用域内的函数和变量才能被执行。
  • globals:这个参数管控的是一个全局的命名空间,即 expression 可以使用全局命名空间中的函数。如果只是提供了 globals 参数,而没有提供自定义的 __builtins__,则系统会将当前环境中的 __builtins__ 复制到自己提供的 globals 中,然后才会进行计算;如果连 globals 这个参数都没有被提供,则使用 Python 的全局命名空间。
  • locals:这个参数管控的是一个局部的命名空间,和 globals 类似,当它和 globals 中有重复或冲突时,以 locals 的为准。如果 locals 没有被提供,则默认为 globals。

注意:__builtins__ 是 Python 的内建模块,平时使用的 int、str、abs 都在这个模块中。通过 print(dic["__builtins__"]) 语句可以查看 __builtins__ 所对应的 value。

首先,通过如下的例子来演示参数 globals 作用域的作用,注意观察它是何时将 __builtins__ 复制 globals 字典中去的:

dic = {}  # 定义一个字典
dic['b'] = 3  # 在 dic 中加一条元素,key 为 b
print(dic.keys())  # 先将 dic 的 key 打印出来,有一个元素 b
exec("a = 4", dic)  # 在 exec 执行的语句后面跟一个作用域 dic
print(dic.keys())  # exec 后,dic 的 key 多了一个

# 运行结果:
# dict_keys(['b'])
# dict_keys(['b', '__builtins__', 'a'])

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

4、eval() 执行完会返回结果,而 exec() 执行完不返回结果

a = 1
exec("a = 2")  # 相当于直接执行 a=2
print(a)

a = exec("2+3")  # 相当于直接执行 2+3,但是并没有返回值,a 应为 None
print(a)

a = eval('2+3')  # 执行 2+3,并把结果返回给 a
print(a)

可以看出,exec() 函数中最适合放置运行后没有结果的语句,而 eval() 函数中适合放置有结果返回的语句。

如果 eval() 里放置一个没有结果返回的语句会怎样呢?例如下面代码:

a = eval("a = 2")

运行结果:这时 Python 解释器会报 SyntaxError 错误,提示 eval()函数 中不识别等号语法。

 

posted @ 2021-04-22 14:39  习久性成  阅读(9091)  评论(0编辑  收藏  举报