在Python中有个神级函数,没错,神级函数,就是eval,它可以实现一些非常牛逼的操作。
语法
它可以将字符串str当成有效的表达式来求值并返回计算结果。
eval(expression,globals=None, locals=None) |
参数
参数 | 描述 |
---|---|
expression | 一个参与计算的python表达式 |
globals | 可选的参数,如果设置属性不为None的话,就必须是dictionary对象了 |
locals | 一个可选的对象,如果设置属性不为None的话,可以是任何map对象了 |
用法
既然说是神级函数,那么他到底有什么用呢?
类型转化
可以把list,tuple,dict和string相互转化。
str转换成list
a = "[[1,2], [3,4], [5,6], [7,8], [9,0]]" |
[[1, 2], [3, 4], [5, 6], [7, 8], [9, 0]] |
str转换成dict
a = "{1: 'a', 2: 'b'}" |
{1: 'a', 2: 'b'} |
用于计算
可以直接输入计算的表达式,就可以直接返回结果,所以用这个函数来写计算器函数是非常好写的,仅仅几行就可以写一个计算器的基本功能。
if __name__ == '__main__': |
请输入计算式:3*7+9 |
使用eval实现完整功能的计算器,请点击这里
插曲-变量寻址
x = 1 |
上面的x,y为全局变量,函数func内的为局部变量。在使用eval函数是可以定义要寻找变量的类型。
重点看下上面代码的num3的值,如果是设定找的是全局变量,那么会返回2,设定局部变量表达式会返回4.
如果并没有设定,默认先寻找local(),
# 搜索变量的优先级顺序是:L > E > G > B |
存在的问题与解决办法
存在的问题就是安全问题了,当然就自己在本地跑脚本玩,也没什么问题,
如果python写的cgi程序中如果使用eval()而非int()来转换诸如年龄这样的输入框中的内容时是非常危险的。不仅可以看见列出系统的全部文件,还可以执行删除文件,察看文件源代码等危险操作!
解决办法
1.法1
eval接受3个参数: eval(source[, globals[, locals]]) -> value
只要将2个命名空间置空即可隔绝上下文的代码进行安全执行表达式。
eval('{1:2}',{},{}) |
不过! 通过builtins内置的方法仍有可能绕过:import(‘os’).system(‘dir’)、 eval(“globals()”, {}, {})。
2.法2
ast模块就是帮助Python应用来处理抽象的语法解析的。而该模块下的literal_eval()
函数:则会判断需要计算的内容计算后是不是合法的python类型,如果是则进行运算,否则就不进行运算。
比如说上面的计算操作,及危险操作,如果换成了ast.literal_eval()
,都会拒绝执行。
嗯,如果使用这个函数做计算器是没戏的。