eval函数

在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]]"
b = eval(a)

print(b)
print(type(b))
[[1, 2], [3, 4], [5, 6], [7, 8], [9, 0]]
<class 'list'>
str转换成dict
a = "{1: 'a', 2: 'b'}"
b = eval(a)

print(b)
print(type(b))
{1: 'a', 2: 'b'}
<class 'dict'>

用于计算

可以直接输入计算的表达式,就可以直接返回结果,所以用这个函数来写计算器函数是非常好写的,仅仅几行就可以写一个计算器的基本功能。

if __name__ == '__main__':
while True :
result = eval(input("请输入计算式:"))
print(type(result))
print(result)
请输入计算式:3*7+9
<class 'int'>
30

使用eval实现完整功能的计算器,请点击这里

插曲-变量寻址

x = 1
y = 1
num1 = eval("x+y")
print(num1)
def func():
x = 2
y = 2
num2 = eval("x+y")
print(num2)
num3 = eval("x+y", globals())
# num3 = eval("x+y", locals())
print(num3)

上面的x,y为全局变量,函数func内的为局部变量。在使用eval函数是可以定义要寻找变量的类型。
重点看下上面代码的num3的值,如果是设定找的是全局变量,那么会返回2,设定局部变量表达式会返回4.
如果并没有设定,默认先寻找local(),

# 搜索变量的优先级顺序是:L > E > G > B

# L:local 局部作用域,即函数中的变量

# E:enclosing,嵌套的父级函数的作用域,即,此函数的上级函数的局部作用域,但不是全聚德

# G:global:全局变量,就是米会计别定义的变量

# B:build-in 系统固定模块里面的变量,如int byte等

存在的问题与解决办法

存在的问题就是安全问题了,当然就自己在本地跑脚本玩,也没什么问题,

如果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(),都会拒绝执行。

嗯,如果使用这个函数做计算器是没戏的。

-------------本文结束感谢您的阅读-------------