Python【4】:eval() & exec()
阿里云国内75折 回扣 微信号:monov8 |
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6 |
文章目录
前言
本文主要介绍了 Python 中一对非常有意思的函数eval()
和 exec()
这一对函数的作用大致相当简单来说都可以执行字符串中的数学表达式且 exec()
函数的作用比 eval()
更大
1. eval()
1.1. 语法
eval()
函数用来执行一个字符串表达式并返回表达式的值。即将字符串当成有效的表达式 来求值并返回计算结果。
eval(expression[, globals[, locals]])
- 参数含义
- expression – 表达式
- globals – 变量作用域全局命名空间如果被提供则必须是一个字典对象
- locals – 变量作用域局部命名空间如果被提供可以是任何映射对象
- 参数用法
- 当后两个参数都为空时就是一个 string 类型的算术表达式计算出结果即可
- 等价于
eval(expression)
- 等价于
- 当 locals 参数为空globals 参数不为空时先查找 globals 参数中是否存在变量并计算
- 当两个参数都不为空时先查找 locals 参数再查找 globals 参数
- 当后两个参数都为空时就是一个 string 类型的算术表达式计算出结果即可
- 返回值
- 返回表达式计算结果
1.2. 命名空间与生命周期
1.2.1. 命名空间
- 定义
- 名称到对象的映射
- Python 通过命名空间来记录变量的轨迹
- 命名空间是一个 dictionary键是变量名值是变量值
- 各个命名空间是独立没有关系的一个命名空间中不能有重名但是不同的命名空间可以重名而没有任何影响
- 名称到对象的映射
- 分类
- Python 程序执行期间会有 2 个或 3 个活动的命名空间函数调用时有3个函数调用结束后2个
- 按照变量定义的位置可以划分为以下 3 类
- Local局部命名空间每个函数所拥有的命名空间记录了函数中定义的所有变量包括函数的入参、内部定义的局部变量
- Global全局命名空间每个模块加载执行时创建的记录了模块中定义的变量包括模块中定义的函数、类、其他导入的模块、模块级的变量与常量
- Built-inPython 自带的内建命名空间任何模块均可以访问放着内置的函数和异常
1.2.2. 生命周期
- 分类
- Local局部命名空间在函数被调用时才被创建但函数返回结果或抛出异常时被删除
- 每一个递归函数都拥有自己的命名空间
- Global全局命名空间在模块被加载时创建通常一直保留直到 Python 解释器退出
- Built-in内建命名空间在 Python 解释器启动时创建一直保留直到解释器退出
- Local局部命名空间在函数被调用时才被创建但函数返回结果或抛出异常时被删除
- 顺序
- 各命名空间创建顺序Python 解释器启动 -> 创建内建命名空间 -> 加载模块 -> 创建全局命名空间 -> 函数被调用 -> 创建局部命名空间
- 各命名空间销毁顺序函数调用结束 -> 销毁函数对应的局部命名空间 -> Python 虚拟机解释器退出 -> 销毁全局命名空间 -> 销毁内建命名空间
1.3. 使用方法
#1.eval无参实现字符串转化
s = '1+2+3*5-2'
print(eval(s)) #16
#2.字符串中有变量也可以
x = 1
print(eval('x+2')) #3
#3.字符串转字典
print(eval("{'name':'linux','age':18}"))
#输出结果{'name':'linux','age':18}
#4.eval传递全局变量参数,注意字典里的:age中的age没有带引号说明它是个变量而不是字符串。
#这里两个参数都是全局的
print(eval("{'name':'linux','age':age}",{"age":1822}))
#输出结果{'name': 'linux', 'age': 1822}
print(eval("{'name':'linux','age':age}",{"age":1822},{"age":1823}))
#输出结果{'name': 'linux', 'age': 1823}
#eval传递本地变量既有global和local时变量值先从local中查找。
age=18
print(eval("{'name':'linux','age':age}",{"age":1822},locals()))
#输出结果{'name': 'linux', 'age': 18}
print("-----------------")
print(eval("{'name':'linux','age':age}"))
2. exec()
2.1. 语法
exec
执行储存在字符串或文件中的 Python 语句相比于 eval
exec
可以执行更复杂的 Python 代码
以用来动态执行字符串代码在 for
循环里面能快速执行大量类似于 list1= 1list2=2list3=3...
这样的语句使代码显得更加简洁
exec(object[, globals[, locals]])
- 参数含义
- object必选参数表示需要被指定的 Python 代码。它必须是字符串或 code 对象。
- 如果 object 是一个字符串该字符串会先被解析为一组 Python 语句然后再执行除非发生语法错误
- 如果 object 是一个 code 对象那么它只是被简单的执行
- globals可选参数表示全局命名空间存放全局变量如果被提供则必须是一个字典对象
- locals可选参数表示当前局部命名空间存放局部变量如果被提供可以是任何映射对象。如果该参数被忽略那么它将会取与 globals 相同的值
- object必选参数表示需要被指定的 Python 代码。它必须是字符串或 code 对象。
- 返回值
exec
返回值永远为None
2.2. 用法
2.2.1. 动态执行简单的字符串代码
i = 12
j = 13
exec("answer=i*j")
print("Answer is %s"%answer)
这表明第三句的 exec()
函数能够正确地执行 Python 代码并且能将计算结果赋予 answer 变量就像真正的 Python 代码一样
2.2.2. 动态执行较复杂的代码
func = "def fact(n):\n\treturn 1 if n==1 else n*fact(n-1)"
exec(func)
a = fact(5)
print(a)
func 是字符串它是一个递归地计算整数阶乘的函数。因为 exec()
仅支持 string 和 code object 参数所以我们要将该递归函数转化成一个字符串当然格式还是要 Python 代码的格式来注意换行和缩进
2.2.3. 执行文件中的 Python 代码
假设有 eg.txt 文件存储如下 Python 语句
def fact(n):
if n==1:
return 1
else:
return n*fact(n-1)
t = fact(6)
print(t)
这是一个 txt 格式的 Python 代码我们可以使用 exec()
语句运行它
with open('eg.txt', 'r') as f:
s = f.read()
exec(s)
在上述代码中我们先读取 eg.txt 文件的内容再转交 exec()
函数执行
2.2.4. 传参
除了能执行 string 和 code object 外还可以在 exec()
函数中加入参数参数的传递可以写成字典 (dict) 形式
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()
语句分析
- 在 expr 语句中有三个变量
x
,
y
,
z
x, y, z
x,y,z 其中
z
z
z 值已给定
- 我们可以在
exec()
函数外指定 x , y x, y x,y 的值 - 也可以在
exec()
函数中以字典的形式指定 x , y x, y x,y 的值
- 我们可以在
- 在最后的语句中我们给出了
x
,
y
,
z
x, y, z
x,y,z 的值并且
y
y
y 值重复
exec()
函数接收后面一个 y y y 值且 z z z 值传递不起作用