Python 基础教程

Python 流程控制

Python 函数

Python 数据类型

Python 文件操作

Python 对象和类

Python 日期和时间

Python 高级知识

Python 参考手册

Python eval() 使用方法及示例

Python 内置函数

eval()方法解析传递给该方法的表达式,并在程序中运行python表达式(代码)。

简而言之,eval()方法在程序内运行python代码(作为参数传递)。

eval()的语法为:

eval(expression, globals=None, locals=None)

eval()参数

eval()具有三个参数:

  • expression-解析并评估为Python表达式的字符串

  • globals(可选)-字典

  • locals(可选)-映射对象。字典是Python中常用的标准映射类型。

稍后将在本文中讨论全局变量(globals)本地变量(locals)的使用。

eval()返回值

eval()方法返回从expression求值的结果。

示例1:eval()如何在Python中工作?

x = 1
print(eval('x + 1'))

运行该程序时,输出为:

2

在这里,eval()计算表达式x + 1并打印出来。

示例2:演示使用eval()的实际示例

# 正方形的周长
def calculatePerimeter(l):
  return 4*l

# 面积的平方
def calculateArea(l):
  return l*1

property = input("输入要使用的函数: ")

for l in range(1, 5):
    if (property == 'calculatePerimeter(l)'):
        print("如果长度是 ", l , ", 周长 = ", eval(property))
    elif (property == 'calculateArea(l)'):
        print("如果长度是  ", l , ", 面积 = ", eval(property))
    else:
      print('错误的功能')
      break

上面程序的输出将是:

输入要使用的函数: calculatePerimeter(l)
如果长度是  1 , 周长 =  4
如果长度是  2 , 周长 =  8
如果长度是  3 , 周长 =  12
如果长度是  4 , 周长 =  16

为什么在使用eval()时要小心?

考虑一种情况,您正在使用Unix系统(macOS,Linux等),并且已导入os模块。os模块提供了使用操作系统功能的便携式方法,例如:读取或写入文件。

如果允许用户使用来输入值eval(input()),则用户可以发出命令来更改文件,甚至可以使用command删除所有文件os.system('rm -rf *')。

如果eval(input())在代码中使用,最好检查用户可以使用哪些变量和方法。您可以使用dir()方法查看可用的变量和方法。

from math import *
print(eval('dir()'))

当您运行该程序时,输出将类似于:

['__annotations__', '__builtins__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'acos', 'acosh', 'asin', 'asinh', 'atan', 'atan2', 'atanh', 'ceil', 'copysign', 'cos', 'cosh', 'degrees', 'e', 'erf', 'erfc', 'exp', 'expm1', 'fabs', 'factorial', 'floor', 'fmod', 'frexp', 'fsum', 'gamma', 'gcd', 'hypot', 'inf', 'isclose', 'isfinite', 'isinf', 'isnan', 'ldexp', 'lgamma', 'log', 'log10', 'log1p', 'log2', 'modf', 'nan', 'pi', 'pow', 'radians', 'sin', 'sinh', 'sqrt', 'squareRoot', 'tan', 'tanh', 'tau', 'trunc']

限制在eval()中使用可用的方法和变量

通常,可能不需要使用表达式(eval()的第一个参数)中使用的所有可用方法和变量,甚至可能有安全漏洞。您可能需要限制将这些方法和变量用于eval()。您可以通过将可选的globalslocals参数(字典)传递给eval()方法来实现。

1.当省略globals和locals参数时

如果两个参数都被省略(如前面的示例所示),则在当前范围内执行该表达式。您可以使用以下代码检查可用的变量和方法:

print(eval('dir()'))

2.传递全局参数;省略locals参数

globals和locals参数(字典),分别用于全局和局部变量。如果省略了locals字典,则默认为globals字典。这意味着,globals将用于全局变量和局部变量。

注意:您可以分别使用globals()locals()内置方法在Python中检查当前的全局字典和局部字典。

将空字典作为全局参数传递

from math import *
print(eval('dir()', {}))

# 下面的代码将引发异常
# print(eval('sqrt(25)', {}))

如果将空字典作为globals传递,则仅__builtins__可用于表达式(expression)(eval()的第一个参数)。即使我们在上面的程序中导入了math模块,表达式(expression)也无法访问math模块提供的任何功能。

运行该程序时,输出为:

['__builtins__']

使某些方法可用

from math import *
print(eval('dir()', {'sqrt': sqrt, 'pow': pow}))

在此,表达式还可以使用sqrt()和pow()方法以及__builtins__。

另外,可以根据您的意愿更改可用于表达式(expression)的方法的名称。

from math import *
print(eval('dir()', {'squareRoot': sqrt, 'pow': pow}))

# 在表达式中使用平方根
print(eval('squareRoot(9)', {'squareRoot': sqrt, 'pow': pow}))

在上述程序中,squareRoot()计算平方根(类似的功能,如sqrt())。但是,尝试使用sqrt()将引发错误。

限制使用__builtins__

您可以按以下方式限制__builtins__在表达式(expression)中的使用:

eval(expression, {'__builtins__': None})

3.通过全局和本地字典

您可以通过传递本地(locals)字典来使所需的函数和变量可用。例如:

from math import *

a = 5
print(eval('sqrt(a)', {'__builtins__': None}, {'a': a, 'sqrt': sqrt}))

运行该程序时,输出为:

 2.23606797749979

在此程序中,表达式(expression)(eval的第一个参数)只能具有sqrt()方法和变量a。所有其他方法和变量均不可用。

通过传递globalslocals字典来限制eval()的使用将使您的代码安全,尤其是在使用用户提供给eval()方法的输入时。

Python 内置函数