1
  • Editted to take into account initial feedback

To do a sensitivity-analsysis on some of the parameters in my model, I want to overwrite and redefine a single variable. This variable can be handpicked by the user. I cannot get the overwriting to work.

For now, I have focussed mainly on getting the locals() or globals() to the right value, but as shown below. this did not work.

Two important parts of my code: first the Main function, doing all the work to create the model. It has many variables, one is shown: the Wave_height

def Main(loopname, loopvalue = 0):

    Wave_height = 2 #m
    # And_many_other_characteristics

    # redefine one single variable name
    vars()[loopname] = loopvalue
    globals()[loopname] = loopvalue
    locals()[loopname] = loopvalue
    print (Wave_height)

    return_info = 1 ## rows of code i dont want to bother you with ##

    return(return_info)

if __name__ == "__main__":
    Main("testname", 0)

For the sensitivity analysis, I would like to have all variables constant, except for a single variable. Lets assume I want to vary the Wave_height. I want to do something like the following code:

import Main
import numpy as np

loopname = "Wave_height"
loopvalue = [1,2,3]

max_z_displacement = np.zeros(len(loopvalue))

for i in range (len(loopvalue)):
    return_info = Main.Main(loopname, loopvalue[i])
    max_z_displacement[i] = return_info[2]

Currently, the prints are as follows:

2

I would like to have the result being:

1

I would like to avoid using 50 different variables in the def-row, as that would not make it easy to use.

  • 6
    Instead of dynamic variables, use a dictionary containing all the parameters, and pass the dictionary key. – Barmar Sep 24 '19 at 17:17
  • Thank you for your help, but using that exceeds my current level of understanding of python. I read many times online that a dynamic variable is a bad idea, but in my case it is the "quick and dirty"-method to obtain what I would like to obtain. Do you have advise how to provide the desired result without needing to use a complete dict? – The Olegrod Sep 24 '19 at 17:26
  • 1
    What you are attempting is way more advanced than using a dict, and almost certainly the wrong approach. – tripleee Sep 24 '19 at 17:28
  • Then how would I use a dictionary to obtain the desired change of a single parameter from outside of the main function? If I could get the name of the variable as a direct output from the string, I'd be settled. That is why I figured my method would be easy to implement. – The Olegrod Sep 24 '19 at 17:32
  • Use `params[loopname]` instead of `globals()[loopname]`, where `params` is your variable that holds your parameters. There's also no need for `str('{}'.format(loopname))`. `loopname` is already a string. – Barmar Sep 24 '19 at 17:37

1 Answers1

0

To make the called function look natural, pack the parameters in an otherwise featureless object:

class Parameters(object):
  def __init__(self,**attr): vars(self).update(attr)
def calc(**over):
  p=Parameters(Wave_height=2,…)
  vars(p).update(over)
  do_stuff(p.Wave_height,…)
  do_more(p.other_data)
  …

for h in heights:
  calc(Wave_height=h)
  calc(**{"Wave_height":h})  # to choose parameter dynamically
Davis Herring
  • 36,443
  • 4
  • 48
  • 76