我希望程序的用户以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)
有没有这样做?
答案 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
包裹在一个函数中,并授予它对x
和np
名称的访问权限:
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