0

I would like this function to take a string, indicating which data(x, y or z) it should plot, as an argument.

def plotfit(axis):

    fig = plt.figure()
    ax = fig.gca(projection='3d')
    ax.set_xlabel('x')
    ax.set_ylabel('y')
    ax.set_zlabel('z')
    ax.scatter(xdata, ydata, func_z(vars,fitted_z),c='r')
    ax.set_title('B_z of %s' % name)
    ax.scatter(xdata, ydata, zfield, c='b')

How do I make the bolded parts of the code below replaced by my string argument so that, e.g. plotfit(x) would replace all instances of bolded z below with "x" and plot accordingly ? Points of interest:

  • func_z
  • fitted_z
  • zfield
  • 'B_z of %s'

What I imagine would be something along the lines of:

ax.scatter(xdata, ydata, func(axis as a string)(vars,fitted_(axis as a string)),c='r')
joo
  • 3
  • 4

2 Answers2

1

You can use a dictionary that will act as a switch statement in your code as outlined below.

def plotfit(a_letter):
    assert a_letter in ["x", "y", "z"]
    fitted = {"x" : fitted_x, "y" : fitted_y, "z" : fitted_z}
    fields = {"x" : field_x, "y" : field_y, "z" : field_z}
    afunc = {"x" : afunc_x, "y" : afunc_y, "z" : afunc_z}
    # ...
    ax.scatter(xdata, ydata, afunc[a_letter](vars,fitted[a_letter]),c='r')
    #...
    ax.set_title('B_%s of %s' %(a_letter, name))

However, you could also consider the alternatives:

  • Have plotfit to take the functions fitted, func, field as argument
  • Have plotfit to take an object as argument that would have the fitted ,func and field methods
  • Have plotfit defined in a base class and uses self.func, self.fit and self.field. Those methods would be implemented in different subclasses

Note that using exec statement for such a case is seen as bad practice as described in Why should exec() and eval() be avoided?

0

One solution is to use exec to execute different code depending on the string type argument I presume you want to parse to the function, for example:

def plotfit(axis):
    fig = plt.figure()
    ax = fig.gca(projection='3d')
    ax.set_xlabel('x')
    ax.set_ylabel('y')
    ax.set_zlabel('z')
    exec("ax.scatter(xdata, ydata, func_" + axis + "(vars,fitted_" + axis + "),c='r')")

A similar technique can be used for the other lines you want to do this on.

Please bear in mind that it is not recommended to use exec (or eval) as it can often hide bugs and can be ambiguous. See: Why should exec() and eval() be avoided?

Community
  • 1
  • 1
Rob Murray
  • 1,773
  • 6
  • 20
  • 32