python eval()
eval(expression, globals=None, locals=None)
eval()方法解析expression, 并将值返回
参数
expression: 解析的表达式
globals: 字典格式
locals: 官方解释只要是map对象就行,我们一般使用字典
具体globals和loclas怎么用下方例子说明
返回
返回expression的值
例1:
x=1
print(eval("x + 1"))
输出
2
例2
# Perimeter of Square
def calculatePerimeter(l):
return 4*l
# Area of Square
def calculateArea(l):
return l*l
expression = input("Type a function: ")
for l in range(1, 5):
if (expression == 'calculatePerimeter(l)'):
print("If length is ", l, ", Perimeter = ", eval(expression))
elif (expression == 'calculateArea(l)'):
print("If length is ", l, ", Area = ", eval(expression))
else:
print('Wrong Function')
break
输出:
Type a function: calculateArea(l)
If length is 1 , Area = 1
If length is 2 , Area = 4
If length is 3 , Area = 9
If length is 4 , Area = 16
不安全警告:
如果你在使用Unix系列的系统,并且你导入了os模块, 那么所有的用户都可再eval(input())中输入os.system('rm -rf *')删除所有文件夹
那么eval执行的表达式中变量是怎么规定的:
下面
print(eval("a + 1"))
是不能通过的, 因为再这个程序内并没有声明a
正确的方式是:
a = 1024
print(eval("a + 1"))
我们可以使用dir()来查看允许使用的变量都有什么: 如果没有导入math模块:
print(eval("dir()"))
输出:
['__annotations__', '__builtins__', '__doc__', '__loader__', '__name__', '__package__', '__spec__']
导入math模块:
from math import *
print(eval("dir()"))
输出:
['annotations', 'builtins', 'doc', 'loader', 'name', 'package', 'spec', 'acos', 'acosh', 'asin', 'asinh', 'atan', 'atan2', 'atanh', 'ceil', 'comb', 'copysign', 'cos', 'cosh', 'degrees', 'dist', 'e', 'erf', 'erfc', 'exp', 'expm1', 'fabs', 'factorial', 'floor', 'fmod', 'frexp', 'fsum', 'gamma', 'gcd', 'hypot', 'inf', 'isclose', 'isfinite', 'isinf', 'isnan', 'isqrt', 'ldexp', 'lgamma', 'log', 'log10', 'log1p', 'log2', 'modf', 'nan', 'perm', 'pi', 'pow', 'prod', 'radians', 'remainder', 'sin', 'sinh', 'sqrt', 'tan', 'tanh', 'tau', 'trunc']
你会发现多了很多的数学方法
如何解决不安全的问题:
我们可使用globals和locals来规定变量
globals是None
from math import *
print(eval("dir", {}))
print(eval("sqrt(25)", {}))
输出:
['builtins']
Traceback (most recent call last):
File "", line 5, in
print(eval('sqrt(25)', {}))
File "", line 1, in
NameError: name 'sqrt' is not defined
如果globals传入空值,那么只有__builtins__是可以用的, 也就是说只有那些不用导入就能只用的变量才能用(列表, 元组, 字典)
- 我们只允许使用部分变量,来防止不安全发生
from math import *
print(eval("dir()", {"sqrt": sqrt, "pow':pow}))
输出
['__builtins__', 'pow', 'sqrt']
- 当然可以使用自定义的名字
from math import *
names = {'square_root': sqrt, 'power': pow}
print(eval('dir()', names))
# Using square_root in Expression
print(eval('square_root(9)', names))
输出
['__builtins__', 'power', 'square_root']
3.0
如果使用自定义名字, 那么你在使用sqrt是会报错的。
- 禁止使用不用导入的模块:
# calculate the length of a tuple
eval("len((1,2,3,4))", {'__builtins__': None})
输出
TypeError Traceback (most recent call last) in ----> 1 print(eval("len((1,2,3,4))", {"builtins":None}))
in
TypeError: 'NoneType' object is not subscriptable
globals和locals的区别: eval会首先再local中查找,如果没有查找到变量或方法,就会在global中查找。 ==下面的例子默认执行from math import *==
eval("dir()", {"sqrt":sqrt, "sin":sin}, {"pow":pow, "sqrt":sqrt})输出
['pow', 'sqrt']
eval("sin_loc(1)", {"sqrt":sqrt, "sin_glo":sin}, {"pow":pow, "sqrt":sqrt, "sin_loc":sin})0.8414709848078965
eval("sin_glo(1)", {"sqrt":sqrt, "sin_glo":sin}, {"pow":pow, "sqrt":sqrt, "sin_loc":sin})0.8414709848078965
虽然math中有sin()方法, 凡是在
globals和'locals'中并没设置,所以异常 eval("sin(1)", {"sqrt":sqrt, "sin_glo":sin}, {"pow":pow, "sqrt":sqrt, "sin_loc":sin})
NameError Traceback (most recent call last) in ----> 1 eval("sin(1)", {"sqrt":sqrt, "sin_glo":sin}, {"pow":pow, "sqrt":sqrt, >"sin_loc":sin})
in
NameError: name 'sin' is not defined