Reputation: 43
I am trying to make a complete function, that takes in an expression:
def graph(formula):
fig = plt.figure()
ax = fig.gca(projection='3d')
X = np.arange(-50, 50, 0.5)
X = X[X != 0]
Y = np.arange(-50, 50, 0.5)
Y = Y[Y != 0]
X, Y = np.meshgrid(X, Y)
Z=[[0],[0]]
expression = "Z=" + formula
exec(expression)
Now I want to do graph("X+Y")
, and then it should do Z = X + Y. It doesn't do that. I have tried doing the same with eval
instead of exec
, but no luck.
Upvotes: 1
Views: 171
Reputation: 82
I assume you mean to pass to your function like so (to calculate Z),
def graph(formula)
...
graph(X+Y)
...
If so, why not just pass to separate values (or arrays of values)? Such as,
def graph(x, y):
...
graph(4, 5)
...
or,
mypoints = [[1, 3], [4, 8], [8, 1], [10, 3]] # 2-D array
def graph(XY):
for point in XY:
x = point[0]
y = point[1]
.... # everything else
graph(mypoints )
...
For a full example of this, check out Method: Stats.linregress( ) in this article (scroll down a bit).
Otherwise, you could:
Formula class
. You could also write a function using the lambda syntax. This would give you the freedom of having an object (like I suggested above) as well as a "function" (of course they are practically synonymous). Read more in the docs.
Upvotes: 0
Reputation: 104792
It sounds like you want to pass a "formula" that computes Z
from X
and Y
. Rather than using exec
or eval
and running into issues with namespaces, a better way to do that is to pass in a function. As user s3cur3 commented, an easy way to do that is with a lambda
expression:
def graph(func):
# set up X and Y up here
Z = func(X, Y)
# do stuff with Z after computing it?
graph(lambda X, Y: X+Y)
If you need more complicated logic that you can fit in a lambda, you can write out a full function if you need to:
def my_func(x, y): # this could be done in a lambda too, but lets pretend it couldn't
if random.random() < 0.5:
return x + y
return x - y
graph(my_func)
Upvotes: 3