Python中eval()、exec()、globals()、locals()与compile()详解

蓝鲸
蓝鲸
发布时间:2026-10-13| 3人浏览过
原创

本文深入解析Python中eval()与exec()函数的核心区别,详细阐述globals()、locals()及compile()函数的定义、参数与返回值机制。通过代码实例说明命名空间在动态执行中的作用,并对比Python 2与Python 3中exec语句的变化,帮助开发者安全高效地使用动态代码执行功能。

前几日有人提及eval()与exec()这两个函数,于是查阅了Python官方文档。本文旨在简要梳理这两个函数及其相关函数,包括globals()、locals()和compile()的使用方法与区别:

1. eval函数

函数作用:

用于计算指定表达式的值。这意味着eval()执行的Python代码仅限于单个运算表达式(注意:eval不支持任何形式的赋值操作),无法处理复杂的代码逻辑,这一点与lambda表达式类似。

函数定义:

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

参数说明:

  1. expression:必选参数,可以是字符串,也可以是任意code对象实例(可通过compile函数创建)。若为字符串,它将被视为一个Python表达式进行分析和解释,并使用提供的globals和locals参数作为全局和本地命名空间。
  2. globals:可选参数,表示全局命名空间(存放全局变量),若提供则必须为字典对象。
  3. locals:可选参数,表示当前局部命名空间(存放局部变量),若提供可以是任何映射对象。若忽略此参数,则其值将与globals相同。
  4. 若globals与locals均被忽略,则它们将默认采用eval()函数调用环境下的全局命名空间和局部命名空间。

返回值:

  1. 若expression是code对象,且创建该code对象时compile函数的mode参数为'exec',则eval()返回None;
  2. 若expression是输出语句(如print()),则eval()返回结果为None;
  3. 否则,expression表达式的计算结果即为eval()函数的返回值;

实例:

x = 10
def func():
  y = 20
  a = eval('x + y')
  print('a: ', a)
  b = eval('x + y', {'x': 1, 'y': 2})
  print('b: ', b)
  c = eval('x + y', {'x': 1, 'y': 2}, {'y': 3, 'z': 4})
  print('c: ', c)
  d = eval('print(x, y)')
  print('d: ', d)
func()

输出结果:

a: 30 b: 3 c: 4 10 20 d: None

对输出结果的解释:

  1. 对于变量a,eval函数的globals和locals参数均被忽略,因此变量x和y取自eval函数调用环境下的作用域,即x = 10, y = 20,故a = x + y = 30
  2. 对于变量b,eval函数仅提供了globals参数而忽略了locals参数,因此locals继承globals的值,即x = 1, y = 2,故b = x + y = 3
  3. 对于变量c,eval函数的globals和locals参数均被提供,eval函数会先从全局作用域globals中查找变量x,再从局部作用域locals中查找变量y,即x = 1, y = 3,故c = x + y = 4
  4. 对于变量d,由于print()函数不是计算表达式,无计算结果,因此返回值为None

2. exec函数

函数作用:

用于动态执行Python代码。与eval()仅能计算单个表达式的值不同,exec()可以执行复杂的Python代码段。

函数定义:exec(object[, globals[, locals]])

参数说明:

  1. object:必选参数,表示需要执行的Python代码。它必须是字符串或code对象。若object是字符串,该字符串会先被解析为一组Python语句然后执行(除非发生语法错误);若object是code对象,则直接执行。
  2. globals:可选参数,含义同eval函数
  3. locals:可选参数,含义同eval函数

返回值:

exec函数的返回值永远为None。

需要注意的是,在Python 2中exec并非函数,而是一个内置语句(statement),但Python 2中有一个execfile()函数。可以理解为Python 3将exec这个statement和execfile()函数的功能整合到了一个新的exec()函数中:

eval()函数与exec()函数的区别:

  1. eval()函数仅能计算单个表达式的值,而exec()函数可以动态运行代码段。
  2. eval()函数可以有返回值,而exec()函数返回值永远为None。

实例1:

我们将实例1中的eval函数替换为exec函数进行测试:

x = 10
def func():
  y = 20
  a = exec('x + y')
  print('a: ', a)
  b = exec('x + y', {'x': 1, 'y': 2})
  print('b: ', b)
  c = exec('x + y', {'x': 1, 'y': 2}, {'y': 3, 'z': 4})
  print('c: ', c)
  d = exec('print(x, y)')
  print('d: ', d)
func()

输出结果:

a: None b: None c: None 10 20 d: None

正如前文所述,exec函数的返回值始终为None。

实例2:

x = 10
expr = """
z = 30
sum = x + y + z
print(sum)
"""
def func():
  y = 20
  exec(expr)
  exec(expr, {'x': 1, 'y': 2})
  exec(expr, {'x': 1, 'y': 2}, {'y': 3, 'z': 4})
func()

输出结果:

60 33 34

对输出结果的解释:

前两个输出与上述eval函数的执行过程解释一致,此处不再赘述。关于最后一个数字34,可以看出x = 1, y = 3是明确的。至于z为何仍为30而非4,理清代码执行过程即可理解,其执行过程相当于:

x = 1
y = 2
def func():
  y = 3
  z = 4
  z = 30
  sum = x + y + z
  print(sum)
func()

3. globals()与locals()函数

函数定义及功能说明:

首先查看这两个函数的定义和文档描述

globals() 

描述: Return a dictionary representing the current global symbol table. This is always the dictionary of the current module (inside a function or method, this is the module where it is defined, not the module from which it is called).

翻译: 返回一个表示当前全局标识符表的字典。这始终是当前模块的字典(在函数或方法内部,指的是定义该函数或方法的模块,而非调用该函数或方法的模块) locals()

描述: Update and return a dictionary representing the current local symbol table. Free variables are returned by locals() when it is called in function blocks, but not in class blocks.

Note The contents of this dictionary should not be modified; changes may not affect the values of local and free variables used by the interpreter.

翻译: 更新并返回一个表示当前局部标识符表的字典。自由变量在函数内部被调用时,会被locals()函数返回;自由变量在类块中不被调用时,不会被locals()函数返回。

注意: locals()返回的字典内容不应被修改;若强行修改,可能不会影响解释器使用的局部变量和自由变量的值。

总结:

  1. globals()函数以字典形式返回定义该函数的模块内全局作用域下的所有标识符(变量、常量等)
  2. locals()函数以字典形式返回当前函数内的局域作用域下的所有标识符
  3. 若直接在模块中调用globals()和locals()函数,它们的返回值是相同的

实例1:

name = 'Tom'
age = 18
def func(x, y):
  sum = x + y
  _G = globals()
  _L = locals()
  print(id(_G), type(_G), _G)
  print(id(_L), type(_L), _L)
func(10, 20)

输出结果:

2131520814344 <class 'dict'> {'__builtins__': <module 'builtins' (built-in)>, 'func': <function func at 0x000001F048C5E048>, '__doc__': None, '__file__': 'C:/Users/wader/PycharmProjects/LearnPython/day04/func5.py', '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x000001F048BF4C50>, '__spec__': None, 'age': 18, '__name__': '__main__', 'name': 'Tom', '__package__': None, '__cached__': None} 2131524302408 <class 'dict'> {'y': 20, 'x': 10, '_G': {'__builtins__': <module 'builtins' (built-in)>, 'func': <function func at 0x000001F048C5E048>, '__doc__': None, '__file__': 'C:/Users/wader/PycharmProjects/LearnPython/day04/func5.py', '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x000001F048BF4C50>, '__spec__': None, 'age': 18, '__name__': '__main__', 'name': 'Tom', '__package__': None, '__cached__': None}, 'sum': 30}

实例2:

name = 'Tom'
age = 18
G = globals()
L = locals()
print(id(G), type(G), G)
print(id(L), type(L), L)

输出结果:

2494347312392 <class 'dict'> {'__file__': 'C:/Users/wader/PycharmProjects/LearnPython/day04/func5.py', '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x00000244C2E44C50>, 'name': 'Tom', '__spec__': None, '__builtins__': <module 'builtins' (built-in)>, '__cached__': None, 'L': {...}, '__package__': None, '__name__': '__main__', 'G': {...}, '__doc__': None, 'age': 18} 2494347312392 <class 'dict'> {'__file__': 'C:/Users/wader/PycharmProjects/LearnPython/day04/func5.py', '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x00000244C2E44C50>, 'name': 'Tom', '__spec__': None, '__builtins__': <module 'builtins' (built-in)>, '__cached__': None, 'L': {...}, '__package__': None, '__name__': '__main__', 'G': {...}, '__doc__': None, 'age': 18}

上述打印出的G和L的内存地址一致,说明在模块级别locals()的返回值与globals()的返回值相同。

4. compile函数

函数作用:

将source编译为code对象或AST对象。code对象可通过exec()函数执行,或通过eval()函数进行计算求值。

函数定义:

compile(source, filename, mode[, flags[, dont_inherit]])

参数说明:

  1. source:字符串或AST(Abstract Syntax Trees)对象,表示需要编译的Python代码
  2. filename:指定需要编译的代码文件名称,若非从文件读取代码,则传递一些可辨认的值(通常使用'<string>')
  3. mode:用于标识必须作为哪类代码来编译;若source由代码语句序列组成,则指定mode='exec';若source由单个表达式组成,则指定mode='eval';若source由单独的交互式语句组成,则指定mode='single'。
  4. 另外两个可选参数暂不作介绍

实例:

s = """
for x in range(10):
  print(x, end='')
print()
"""
code_exec = compile(s, '<string>', 'exec')
code_eval = compile('10 + 20', '<string>', 'eval')
code_single = compile('name = input("Input Your Name: ")', '<string>', 'single')
a = exec(code_exec)
b = eval(code_eval)
c = exec(code_single)
d = eval(code_single)
print('a: ', a)
print('b: ', b)
print('c: ', c)
print('name: ', name)
print('d: ', d)
print('name; ', name)

输出结果:

0123456789 Input Your Name: Tom Input Your Name: Jerry a: None b: 30 c: None name: Jerry d: None name; Jerry

5. 这几个函数的关系

compile()函数、globals()函数、locals()函数的返回结果可作为eval()函数与exec()函数的参数使用。

此外,我们可以通过判断globals()函数的返回值中是否包含某个key,来判定某个全局变量是否已存在(被定义)。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持本站。

相关标签:

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。