Python 如何从字符串绘制数学函数?

Python 如何从字符串绘制数学函数?,python,matplotlib,Python,Matplotlib,我有一个表示函数的字符串,比如“x*(x-32(2/x))”。我正在使用matplotlib,但我不知道如何将此字符串转换为要打印的点数组。您可以使用pythonseval函数将字符串转换为代码,但这是危险的,通常被认为是不好的样式,请参见:。 如果用户可以输入字符串,他们可以输入如下内容 导入子流程;子进程。检查_调用(['rm','-rf','*',shell=True) 因此,请确保您在其中构建了合理的安全性 您可以定义一个接受字符串并返回函数的函数。 我们需要做一些预处理,让用户输入公式

我有一个表示函数的字符串,比如
“x*(x-32(2/x))”
。我正在使用
matplotlib
,但我不知道如何将此字符串转换为要打印的点数组。

您可以使用pythons
eval
函数将字符串转换为代码,但这是危险的,通常被认为是不好的样式,请参见:。 如果用户可以输入字符串,他们可以输入如下内容
导入子流程;子进程。检查_调用(['rm','-rf','*',shell=True)

因此,请确保您在其中构建了合理的安全性

您可以定义一个接受字符串并返回函数的函数。 我们需要做一些预处理,让用户输入公式更像他习惯的那样(^等等):

编辑:第二版–白名单而非黑名单 定义允许和支持的词似乎比将某些词列入黑名单要好:

import re

replacements = {
    'sin' : 'np.sin',
    'cos' : 'np.cos',
    'exp': 'np.exp',
    'sqrt': 'np.sqrt',
    '^': '**',
}

allowed_words = [
    'x',
    'sin',
    'cos',
    'sqrt',
    'exp',
]

def string2func(string):
    ''' evaluates the string and returns a function of x '''
    # find all words and check if all are allowed:
    for word in re.findall('[a-zA-Z_]+', string):
        if word not in allowed_words:
            raise ValueError(
                '"{}" is forbidden to use in math expression'.format(word)
            )

    for old, new in replacements.items():
        string = string.replace(old, new)

    def func(x):
        return eval(string)

    return func


if __name__ == '__main__':

    func = string2func(input('enter function: f(x) = '))
    a = float(input('enter lower limit: '))
    b = float(input('enter upper limit: '))
    x = np.linspace(a, b, 250)

    plt.plot(x, func(x))
    plt.xlim(a, b)
    plt.show()
结果:

$ python test.py
enter function: f(x) = x^2
enter lower limit: 0
enter upper limit: 2

对于恶意用户:

enter function: f(x) = import subprocess; subprocess.check_call(['rm', '-rf', '*'], shell=True)
Traceback (most recent call last):
  File "test.py", line 35, in <module>
    func = string2func(input('enter function: f(x) = '))
  File "test.py", line 22, in string2func
    '"{}" is forbidden to use in math expression'.format(word)
ValueError: "import" is forbidden to use in math expression
import numpy as np
import matplotlib.pyplot as plt

# there should be a better way using regex
replacements = {
    'sin' : 'np.sin',
    'cos' : 'np.cos',
    'exp': 'np.exp',
    '^': '**',
}

# think of more security hazards here
forbidden_words = [
    'import',
    'shutil',
    'sys',
    'subprocess',
]

def string2func(string):
    ''' evaluates the string and returns a function of x '''
    for word in forbidden_words:
        if word in string:
            raise ValueError(
                '"{}" is forbidden to use in math expression'.format(word)
            )

    for old, new in replacements.items():
        string = string.replace(old, new)

    def func(x):
        return eval(string)

    return func