阅读本文大概需要:4 分钟
这次给大家介绍一个相对独立的知识点,也是一个函数 - eval()。
00.强大的伊娃(eval)
eval() 函数功能非常强大,它可以接收一个字符串参数,当把一个字符串传递给 eval() 之后,eval() 会把这个字符串当成一个有效的表达式(所谓表达式就是 eval() 会把字符串的引号去掉,然后将中间的内容当成有效的代码)来求值,并返回计算结果:
In [1]: eval("4 + 5")
Out[1]: 9
In [2]: eval("'x' * 10")
Out[2]: 'xxxxxxxxxx'
在 ipython 中执行上述代码 ,传入一个 4 + 5 的字符串,函数执行之后,会返回一个数字 9;传入一个 'x' * 10 的字符串,函数执行后会返回一个 x 重复 10 次的字符串。
In [3]: type(eval("[1,2,3,4]"))
Out[3]: list
同样,当我们传入一个列表的字符串,eval() 函数执行后,会生成一个列表。
这就是eval() 这个函数的强大之处。
01.魔鬼的伊娃(eval)
接下来给大家介绍一下 eval() 函数的注意事项,通过上一小节,我们知道通过把一个字符串传递给 eval() 函数,eval() 就会把字符串的内容当成 Python 的代码去执行。
一般刚接触到 eval(),都会觉得这个玩意儿简直是太方便了,所以有些同学在写项目的时候动不动就想用 eval(),在这我提醒一下:eval() 虽然爽,用时需谨慎。
切记不要使用 eval() 直接转换用户通过 input 输入的内容。
首先给大家介绍一个小知识:
__import__('os').system('终端命令')
用 __import__ 这个内置方法,通过这个方法导入 os 模块,然后再用 os 模块调用 system 方法,system 方法中可以接收一个字符串参数,我们在字符串中可以指定在终端下可以执行的字符串命令,比如 ls,dir 等。等价于如下代码:
import os
os.system("终端命令")
上述代码执行成功,返回 0,执行失败,返回错误提示信息。
下面我们来看一个带有 input 的样例:
formula = input("请输入:")
print(eval(formula))
运行代码的时候,我们输入 __import__('os').system('ls'),你会发现当前项目目录下所有的文件全部都列表显示了,此处是不是感觉到了一丝危险的味道?
下面我们再来执行一次程序,这次我们输入 __import__('os').system('touch testeval'),touch 是用来创建一个文件,当回车以后,我们会发现,当前目录下多了一个 testeval 的文件,同理 我们输入 __import__('os').system('rm testeval'),rm 是用来删除一个文件,当回车以后,我们发现刚刚创建的 testeval 文件被删除了。
通过上面三个小的操作,是不是体会到了用 eval() 直接转换 input 带来的后果?这种方式真的是太可怕了,你的项目再也没用安全性可言,随随便便的输入就可以查看你的代码,也可以随意删除你的文件,到时候哭都没地方哭去。
所以使用 eval() 函数,在享受它方便性的同时,也要有安全性的考量。