1、exec
函数exec将字符串作为代码执行
exec("print('Hello,world!')")
Hello,world!
然而,调用函数exec时只给它提供一个参数绝非好事。大多数情况下,还应向它传递一个命名空间——用于放置变量的地方;否则代码将污染你的命名空间,即修改你的变量。例如,假设代码使用了名称sqrt
,结果将如何呢?
from math import sqrt
exec('Sqrt = 1', scope)
sqrt(4)
输出:
TypeError Traceback (most recent call last)
<ipython-input-34-317e033d29d5> in <module>
----> 1 sqrt(4)
TypeError: 'int' object is not callable
既然如此,为何要将字符串作为代码执行呢?函数exec
主要用于动态地创建代码字符串。如果这种字符串来自其他地方(可能是用户),就几乎无法确定它将包含什么内容。因此为了安全起见,要提供一个字典以充当命名空间。
from math import sqrt
scope = {}
exec('sqrt = 1', scope)
sqrt(4)
输出:
2.0
如你所见,可能带来破坏的代码并非覆盖函数sqrt
。函数sqrt
该怎样还怎样,而通过exec执行赋值语句创建的变量位于scope
中。
请注意,如果你尝试将scope
打印出来,将发现它包含恶化你多内容,这是因为自动在其中添加了包含所有内置函数和值的字典__builtins__
。
len(scope)
输出
2
scope.keys()
输出
dict_keys(['__builtins__', 'Sqrt'])
2、eval
eval是一个类似于exec的内置函数。exec执行一系列Python语句,而eval计算用字符串表示的Python表达式的值,并返回结果(exec什么都不返回,因为它本身是条语句)。例如,你可使用如下代码来创建一个Python计算器:
eval(input("Enter an arithmetic expression: "))
输出
Enter an arithmetic expression: 10+13**2
179
与exec一样,也可以向eval提供一个命名空间,虽然表达式通常不会像语句那样给变量重新赋值。