I want the user of my program to input a mathematical function of their choosing in numpy notation so that I can operate on it. For example:
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
with the code above, the user is inputting the exponential function, which is saved to a variable 'f' - more generally, I would like any mathematical function to be given as input and for it to be stored somehow as a python function. Pseudocode for this may be something like:
def F(x):
f = eval(input("Please enter function in numpy notation:"))
return f
which, if we use the exponential function again as an example, would be equivalent to hard coding:
def F(x):
return np.exp(x)
One more example for clarity.
def F(x):
f = eval(input("Please enter function in numpy notation:"))
return f
>>> x*np.sin(x)
The user input x*np.sin(x) on the command line, which is equivalent to hard coding:
def F(x):
return x*np.sin(x)
Is there anyway to do this?
Consider using numexpr
module .
Example:
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,)
it's also often faster than 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)
When you do f = eval(input("Please enter function in numpy notation:"))
The input by the user gets interpreted as if you had written it in your file. So if your user inputs x+1
then your python script will try to do x+1
in that line.
If you want that line to create a function your user will have to enter something that evaluates to an actual function. That could be something like lambda x: x+1
which returns a function with one argument (x), calculating x+1
. Of course you could also add the lambda x:
in your code. Small Example:
def F(x):
return eval("lambda x:" + input("Please input a function in numpy notation!"))
x = 1
f = F(x)
print(f(x))
Of course this will require that the variable is always called x
.
If you execute above code and enter eg x+1
the output is 2.
A simple solution would we to just wrap eval
in a function and give it access to the names x
and 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...
Note that eval
is highly unsafe. Nothing prevents the user from entering evil code. If you care a tad bit about safety (or performance), @MaxU's answer is preferable.
If you plan to call the function often, it makes sense to pre-compile it:
i = input("fn: ") # enter function once
i = compile(i, 'input', 'eval')
The resulting code object can be passed to eval
just like a string.
Timing the input 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
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.