Alastair Wee
Alastair Wee

Reputation: 21

In Python: How do I convert a user input into a piece of code?

I have a function involves a double integration from -10 to 10 in x and -10 to 10 in y, and I am using the built in quadrature function in SciPy to do this. However, the exact function that needs to be integrated needs user input.

The function is A*cos(x+y), where A needs to be a user input function.

For example, sometimes the function is a constant, and A is 2. So the integral will be of 2*cos(x+y) from -10 to 10 in both x and y. I want the user to input 2 when prompted for A.

But sometimes, the user may want A to be sin(x). So the integral will be of sin(x)*cos(x+y) from -10 to 10 again. I want the user to input np.sin(x) when prompted for A.

Or maybe the user might need A to be np.pi*y*e^(x/3).

A is a string when user inputs value. How do I get it to become a piece of code such that if the user inputs np.sin(x), then later on in the code at the quadrature, Python reads it as np.sin(x)*np.cos(x+y)?

I'm okay if the user inputs wrongly (say, he misspells np.sin as np.siin) and an error is returned.

What I have written is below:

import numpy as np
from scipy.integrate import dblquad

A = input('Enter your function here: ')

def function(x,y):
    return A*(np.cos(x+y))

integral = dblquad(function, -10, 10, lambda x:-10, lambda x:10)

print integral

Appreciate any help given.

Upvotes: 2

Views: 3012

Answers (2)

Burhan Khalid
Burhan Khalid

Reputation: 174624

I would suggest the following approach, its not foolproof, but should catch the majority of cases:

  1. First, make sure the libraries you are using are imported.
  2. Apply the following rules on the user's input:

    1. Try to convert it to a number with int, if this fails:
    2. See if there is a . in the input, split on this .
      1. If the left part of the . is not a module, then its invalid input.
      2. Take the right hand side of the . and then trim it down to the last (
      3. Check if this value is an attribute of the module, and is a callable. If its not, its invalid input.
      4. If it is, use partials to call it, and then chain the rest of your formula.
    3. If the input does not contain a ., check if it contains a (, and trim to this (.
    4. See if the result is a callable, use partials to call it.

Here is some code:

import functools
import re

i = 'math.sin(12)'
try:
   i = int(i)
except ValueError:
   bits = i.split('.')
   if len(bits) > 1:
       module = bits[0]
       callable = bits[1][:bits[1].rfind('(')]
       args = re.search(r'\((.*?)\)', i).groups()[0]
       if hasattr(module, callable):
          f = functools.partial(getattr(module, callable), args)

After this point, f will be the function that you can call. There are some issues with this code though:

  1. It doesn't account for all cases, most prominently if a user enters a function without a module, you'll have to handle this part.

  2. It doesn't handle complex nested function calls.

Hopefully though, you can build on this for your specific use case.

Upvotes: 2

Sander
Sander

Reputation: 621

I am pretty sure you can archieve this using the "eval" function. https://docs.python.org/2/library/functions.html#eval

Careful though, this function executes user input and this can be a security risk.

Edit: In your function replace the A variable by eval(A). Assuming this is a valid function this should work.

Upvotes: 0

Related Questions