Python eval() vs. exec()

2024年8月29日 | 阅读 7 分钟

Python 的 eval() 和 exec() 函数是强大的工具,它们允许在程序中动态执行代码。

虽然它们初看起来很相似,但在功能和目的上却有明显的区别。

在本文中,我们将详细探讨这些函数,并提供示例来说明它们的功能和用例。

eval() 函数

定义:Python 中的 eval() 函数会计算给定的表达式并返回其结果。

它接受一个字符串作为参数,并将其解释为 Python 表达式,在当前作用域内执行。

eval() 函数语法


参数类型详细信息
表达式必需表示要计算的有效 Python 表达式的字符串。
globals可选包含全局变量的字典。
locals可选包含局部变量的字典。

以下是一些示例,展示了 eval() 的工作原理

示例 1 - 计算算术表达式

我们可以使用 eval 函数来计算算术表达式。

输出

Result = 14

说明

在此示例中,表达式 "2 + 3 * 4" 由 eval() 计算。它执行必要的计算并返回结果,然后打印该结果。

示例 2 - 计算变量

我们可以使用 eval 函数来计算包含变量的算术表达式。

输出

Result = 7

说明

在此示例中,表达式 "x + 2" 包含一个变量 'x',该变量使用 eval() 函数进行计算。由于 x 已定义且值为 5,因此表达式成功计算,结果为 7。

示例 3 - 计算函数调用

输出

Result = 16

说明

在此示例中,表达式 "square(4)" 由 eval() 函数计算。它使用参数 4 执行 square() 函数,并返回结果,然后打印该结果。

示例 4 - 计算列表推导式

以下是我们可以使用 eval 函数执行列表推导式的方法。

输出

Result = [1, 4, 9, 16, 25]

说明

在此示例中,表达式 "[x ** 2 for x in numbers]" 由 eval() 函数计算。它通过对 numbers 列表的每个元素进行平方来创建一个新列表,并打印结果列表。

示例 5 - 计算条件表达式

eval() 函数允许我们计算条件表达式。以下是我们如何做到这一点。

输出

Result = 10

说明

在此示例中,表达式 "x if x > y else y" 由 eval() 函数计算。它比较 x 和 y 的值,如果 x 更大,则返回 x;否则返回 y。在这种情况下,结果为 10。

注意:当我们需要动态计算表达式或根据用户输入执行计算时,eval() 函数特别有用。

何时使用 eval()

何时使用 eval() 取决于具体需求。以下是一些可以使用 eval() 函数的场景。

  • 当我们想计算数学表达式或动态执行用户提供的表达式时。
  • 当我们想解释并执行返回值的代码片段时。
  • 当我们想根据用户输入执行计算时。

exec() 函数

定义:与 eval() 不同,Python 中的 exec() 函数用于执行代码块或脚本。

它接受一个包含 Python 代码的字符串作为参数,并在当前作用域内执行。

exec() 函数语法


参数类型详细信息
表达式必需表示要执行的代码块或脚本的字符串。
globals可选包含全局变量的字典。
locals可选包含局部变量的字典。

以下是一些示例,说明 exec() 的工作原理

示例 1:执行简单的代码块

我们可以使用 exec() 函数执行一段代码。

输出

Result = 8

说明

在此示例中,字符串 'source' 包含一个简单的代码块,该代码块将值赋给 x = 5 和 y = 3 变量,并打印它们的和。exec() 函数执行此表达式,结果为 output = 8。

示例 2:执行函数定义

我们可以使用 exec() 函数执行包含函数定义和函数调用的代码。

输出

Result = 6

说明

在此示例中,源代码定义了一个 multiply() 函数,然后使用参数 2 和 3 调用它。exec() 函数执行此代码并产生输出 6。

示例 3:修改全局变量

我们可以使用 exec() 函数执行修改全局变量的源代码。

输出

Original X = 10
Modified X = 11

说明

在此示例中,源代码定义了一个 increment() 函数,该函数通过将全局变量 x 增加 1 来修改其值。exec() 函数执行此代码,导致 x 的值为 11(x 的值增加了 1)。

示例 4:执行循环

我们可以使用 exec() 函数执行包含循环的源代码。

输出

i = 0
i = 1
i = 2
i = 3
i = 4

说明

在此示例中,源代码包含一个 for 循环,该循环打印从 0 到 4 的数字。exec() 函数执行此代码,产生预期的输出。

示例 5:动态代码生成

我们可以使用 exec() 函数执行动态生成的代码。

输出

variable_name = 42

说明

在此示例中,使用字符串格式化动态生成源代码,包括变量名及其初始值。exec() 函数执行此代码,结果为 output = 42。

注意:动态生成的代码是指在运行时根据某些条件或变量创建可执行代码的过程。

当我们需要以下功能时,exec() 函数特别有用

  • 执行动态或用户生成的代码,
  • 实现代码生成器,
  • 或在运行时动态修改程序的行为。

然而,与 eval() 类似,在使用 exec() 时必须格外小心,以避免安全风险,因为它会执行任意代码。

何时使用 exec()

何时使用 exec() 也取决于具体需求。以下是一些可以使用 exec() 函数的场景

  • 当我们想执行更大的代码块或脚本时。
  • 当我们想在当前作用域内修改变量或定义函数时。
  • 当我们想动态生成代码或实现代码生成器时。

eval() 和 exec() 之间的主要区别

虽然 eval() 和 exec() 有一些相似之处,但它们在主要目的和可处理的代码类型方面有所不同。

以下是这些函数之间的主要区别

eval()exec()
功能eval() 计算表达式并返回结果。exec() 执行代码块或脚本。
返回值eval() 返回计算表达式的结果。exec() 不返回值。它只是执行代码。
输入类型eval() 接受一个字符串作为参数,其中包含单个表达式。exec() 接受一个包含多行代码或脚本的字符串。
变量作用域eval() 在当前作用域内运行exec() 可以使用 global 或 nonlocal 关键字修改当前作用域中的变量。
安全隐患这两个函数都可以执行任意代码,因此必须对代码进行净化,以避免任何潜在的漏洞。

结论

eval() 和 exec() 函数都是 Python 的内置函数,是动态代码执行的强大工具。重要的是要知道在需要时如何使用它们。

  • 当我们想计算数学表达式、动态执行用户提供的表达式或根据用户输入执行计算时,eval() 函数非常适合。
  • 另一方面,exec() 函数适用于执行更大的代码块或脚本。
  • 我们需要谨慎执行来自随机来源的代码。因为如果我们使用这些函数执行一些随机脚本。它们会窃取我们计算机上的信息,并在后台安装恶意软件。这可能对我们和我们的组织来说是一个巨大的安全风险。
  • 对输入(源代码)进行仔细验证和净化有助于防止安全漏洞。
  • eval() 和 exec() 之间的主要区别包括它们可以处理的输入类型、它们的返回值、它们操作的变量作用域以及执行任意代码相关的安全问题。

了解它们的区别和适当的用例,可以帮助我们有效地利用它们,同时确保代码的安全性和可靠性。