如何使用'input'在python 3.x中输入数学函数作为变量

时间:2017-12-11 10:50:55

标签: python numpy input

我希望程序的用户以numpy表示法输入他们选择的数学函数,以便我可以对它进行操作。例如:

import numpy as np
f=eval(input("Please input your function in numpy notation")

>>> "Please input your function in numpy notation"
>>> np.exp(x)
>>> NameError: name 'x' is not defined

使用上面的代码,用户正在输入指数函数,该函数被保存到变量'f' - 更一般地说,我希望任何数学函数都作为输入给出,并且它以某种方式存储为python功能。伪代码可能类似于:

def F(x):
    f = eval(input("Please enter function in numpy notation:"))
    return f

,如果我们再次使用指数函数作为例子,则相当于硬编码:

def F(x):
    return np.exp(x)

另一个清晰的例子。

def F(x):
    f = eval(input("Please enter function in numpy notation:"))
    return f

>>> x*np.sin(x)

用户在命令行输入x * np.sin(x),相当于硬编码:

def F(x):
    return x*np.sin(x)

有没有这样做?

3 个答案:

答案 0 :(得分:5)

考虑使用numexpr module

示例:

In [23]: import numexpr as ne

In [24]: a = np.arange(1e6)

In [25]: s = "sin(a)**2 + cos(a)**2"

In [27]: res = ne.evaluate(s)

In [28]: res
Out[28]: array([ 1.,  1.,  1., ...,  1.,  1.,  1.])

In [29]: res.shape
Out[29]: (1000000,)

它通常也比Numpy快:

In [32]: %timeit ne.evaluate(s)
11.4 ms ± 256 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

In [33]: %timeit np.sin(a)**2 + np.cos(a)**2
41 ms ± 1.15 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

答案 1 :(得分:1)

执行f = eval(input("Please enter function in numpy notation:"))时,用户的输入会被解释为您已将其写入文件中。因此,如果您的用户输入x+1,那么您的python脚本将尝试在该行中执行x+1

如果您希望该行创建一个函数,您的用户必须输入一些评估为实际函数的函数。这可能类似于lambda x: x+1,它返回一个带有一个参数(x)的函数,计算x+1。当然,您也可以在代码中添加lambda x:。小例子:

def F(x):
    return eval("lambda x:" + input("Please input a function in numpy notation!"))

x = 1
f = F(x)
print(f(x))

当然,这将要求变量始终被称为x

如果您执行上述代码并输入例如x+1输出为2。

答案 2 :(得分:1)

一个简单的解决方案是,我们只需将eval包裹在一个函数中,并授予它对xnp名称的访问权限:

import numpy

i = input("fn: ")  # enter function once

def f(x):
    return eval(i, {'x': x, 'np': numpy})

f(42)  # call it
f(0)  # call it again...

请注意,eval非常不安全。没有什么能阻止用户输入恶意代码。如果您对安全性(或性能)有点关注,@ MaxU的答案更可取。

如果您打算经常调用该函数,那么预编译它是有意义的:

i = input("fn: ")  # enter function once
i = compile(i, 'input', 'eval')

生成的代码对象可以像字符串一样传递给eval

定时输入np.exp(x)

%timeit f(0.5)  # Without pre-compilation
# 100000 loops, best of 3: 14.2 µs per loop

%timeit f(0.5)  # With pre-compilation
# 100000 loops, best of 3: 1.72 µs per loop