Passing Numbers to a Sympy function in Python - python-3.x

I am practicing Python from Codewars. One of the questions was to take a function as an input given in string from, differentiate it and use the other input given as an integer and return the result. For example lets say the inputs are
stringf=x**2+2x
inputint=3
def differentiate(stringf,inputint) should return 8. I managed to do this by using Sympy and eval. However when I take the derivate of the function with sympy.diff it converts a regular lambda function to something else which you cannot pass arguments. For example you can do f(1) in below code but you cannot do deffunc(1) it throws the error "TypeError: 'Add' object is not callable" because the type of deffunc becomes "<class 'sympy.core.add.Add'>" after sympy.diff.
def differentiate(equation, point):
import sympy as sym
f=lambda x:equation #turn the string into a formula with x
x= sym.symbols('x')
deffunc=sym.diff(f(x),x) #differentiate with respect to x
strfunc=str(deffunc) #convert the function to a string to be used in eval
x=point
f=eval(strfunc)
return f
I found a workaround by simply converting it to string then using eval but I was wondering is there a better way to pass the 'point' into the 'deffunc'?

Related

Most beautiful way of chaining a list of functions in python/numpy

I have a list of numpy functions
fcts = [lambda x : np.power(x,2),np.sqrt,lambda x : np.add(x,3.)]
that I want to apply to an input x by chaining, i.e.
np.power(np.sqrt(np.add(x,3.)),2)
(or the other way around)
Is there an intrinsic numpy function for that or what is the most elegant/fastest way to do that (for a large list of functions) instead of
input = np.random.uniform(0,1,(2,3))
for fct in fcts:
input = fct(input)
Edit:
Numpy is written in C++ and I am wondering, wether there is any 'loss in speed' when the results are converted to python between the functions (and assigned to the variable input).
Here, reduce() from the functools module can do the trick, although I believe the underlying behaviour is pretty close to what you did.
import functools
functools.reduce(lambda o, func: func(o), fcts , input_object)

Does Python implement short-circuiting in built-in functions such as min()?

Does Python 3 implement short-circuiting in built-in functions whenever possible, just like it does for boolean statements?
A specific example, take the below code snippet:
min((20,11), key = lambda x : x % 10) # 20
Does Python evaluate beforehand that the minimum value possible of the function passed as the key argument is 0, and therefore stops right after evaluating the first integer in the iterable passed (20) as 20 % 10 is equal to 0?
Or does it have to evaluate all the elements in the iterable before returning the answer?
I guess short-circuiting isn't even always possible especially for more complex functions, but what about for well-known, built-in functions or operators like %?
I couldn't find the answer in the official docs.
Thanks,
python has to evaluate all values inside the iterable because the languaje evaluate element by element, if you have in your tuple something that is not a number it will trigger an exception when try to perform the % operation. Python can not guess what is inside your list. You can test this by defining a function instead of a lambda and set debug point inside.
def my_mod(x):
import ipdb; ipdb.set_trace()
return x % 20
then call the function
min((20,11), key = my_mod)
you can do a quick error test case with
min((20,11, "s"), key = my_mod)
It will trigger an exception but first had to evaluate all the previous element in the list.

How can i subs or replace a sympy function to a sympy symbol

Im trying to replace the sympy function x(t) to the sympy symbol x.
It should be like something like this:
Before the replace:
funcion0=t**2*sp.cos((x(t)/2))
After the replace:
funcion1=t**2*sp.cos((x/2))
import sympy as sp
t = sp.Symbol('t')
x = sp.Function('x')
funcion=t**2*sp.cos((x(t)/2))
def replace(funcion):
funcion1=funcion.subs(x(t), x)
return funcion1
I know that doesnt work, but maybe it helps to understand what im saying hahaha.
Thanks!!!!
When working with SymPy, it's best to keep in mind the differences between functions, symbols and physical numbers like floats or ints. Here, you want the function x (evaluated at t) to be substituted with the symbol x. If you are uncertain at any point, it is best to add what the type of the variable to its name as I have done below:
import sympy as sp
t, x_sym = sp.symbols('t x')
x_func = sp.Function('x')
function = t**2*sp.cos((x_func(t)/2))
def replace(funcion):
function1 = funcion.subs(x_func(t), x_sym)
return function1
print(replace(function))
It should give you the desired result.

Python Function returning "function at" rather than numerical value

I want the below code to return a numerical value as opposed to <function exp at 0x101c22e18>:
def exp(x,y):
x**y
print(f"exp of {x} to the {y}")
return exp
test1 = 2
test2 = 2
testing = exp(test1, test2)
print(testing)
Why isn't my print statement returning 4?
If your intention is to output the value of x^y. You need to write
return x**y
Not return the function handle exp()
As Argyll has pointed out, the problem is in the function definition. Instead of:
def exp(x,y):
x**y
print(f"exp of {x} to the {y}")
return exp
you should write:
def exp(x,y):
result = str(x**y)
return print(f"{result} is the value of {str(x)} to the {str(y)}")
In your version, you just returned the function itself (and that's what you got: the function object ). In my version, you'd be returning the result of the function. You don't want the function back, you want what the function does back. And you want it back as a string which is why I've used the str() function: to convert integers and/or floats to their string equivalents.
Yes, you can return a function from a function--it's an "object" like any other--and there are many uses of this capability. In your case, though, you want the result of x**y back and not the function itself.
Note that the "f" formatting you used is only available in Python 3.6 or higher.

using concatenated strings as function call in python

I have a a function that takes as input 2 strings and a tuple of points. Based on the combination of those two strings, a specific function should be called on the tuple. I know that I could program some nested if statements, but I'm interested in the idea of calling an existing function from a string.
For example, I have a conversion function 'foo2bar(points)' which converts 'foo' points to 'bar' points. I have many other types of points and conversions between them. I now want to implement a 'type2type(points, oldtype, newtype)' which takes strings oldtype and newtype, and baed on those strings should call the appropriate conversion.
If I call type2type(points, 'foo','bar'), I want it to result in calling foo2bar(points).
Is there a way to generate function calls by concatenating strings like that? I want to say something like functionName = oldtype + '2' + newtype and then call 'functionName somehow.
Well, this isn't the safest way to do things, by you could use eval. Using the code you posted at the bottom, functionName = oldtype + '2' + newtype, you could just do:
functionName = oldtype + '2' + newtype
args = [] #whatever arguments you want in the function
eval(functionName+"(**args)")
You're almost there: after you've constructed functionName you just need to find the function. If your functions are all in a class, you could write something like this:
def type2type(self, points, x, y):
name = '{}2{}'.format(x, y)
if hasattr(self, name):
return getattr(self, name)(points)
else:
raise ValueError("No function named {}".format(name))
If they're module-level functions, you can look for them in globals:
def type2type(points, x, y):
name = '{}2{}'.format(x, y)
if name in globals():
return globals()[name](points)
else:
raise ValueError("No function named {}".format(name))

Resources