Issue
I start up sessions in Jupyter with Python with a partly tailor-made script for the application I work with. The script contains both application dependent dictionaries and functions, but some function are of a general kind. I would like to make a general module and make the start-up script contain only application parts. The difficulty is that I want the functions in the general module have application dictionaries as default. So how to connect such workspace dictionaries to the imported functions?
A very simplifed example below illustrate the problem. First you see the original total startup script. This codes works.
import numpy as np
import matplotlib.pyplot as plt
parDict = {}
parDict['Y'] = 0.5
parDict['qSmax'] = 1.0
parDict['Ks'] = 0.1
def par(parDict=parDict, *x, **x_kwarg):
""" Set parameter values if available in the predefined dictionaryt parDict. """
x_kwarg.update(*x)
x_temp = {}
for key in x_kwarg.keys():
if key in parDict.keys():
x_temp.update({key: x_kwarg[key]})
else:
print(key, 'seems not an accessible parameter')
parDict.update(x_temp)
And I can in the notebook give a command like par(Y=0.4) and then inspect the results in the dictionary parDict.
Second (below) you see an attempt to break out the general functions into a module and this functions are imported in the start-up script. And below the actual module. This code does not work. The error message is: name 'parDict' is not defined How to fix it?
parDict = {}
parDict['Y'] = 0.5
parDict['qSmax'] = 1.0
parDict['Ks'] = 0.1
from test_module import par
And test_module.py
def par(parDict=parDict, *x, **x_kwarg):
""" Set parameter values if available in the predefined dictionaryt parDict. """
x_kwarg.update(*x)
x_temp = {}
for key in x_kwarg.keys():
if key in parDict.keys():
x_temp.update({key: x_kwarg[key]})
else:
print(key, 'seems not an accessible parameter')
parDict.update(x_temp)
If I in the function take away the default argument parDict then it works, but I must then have a lengthier call like par(parDict, Y=0.4). I would like avoid this lengthy call and provide the default parDict automatically. One idea is to in the start-up script make a new function from the imported function and here make the connection to the dictionary. But seems a clumsy way to do it, or the only choice?
Solution
Now I have put together an even better solution that I want to share with you! The key is to make use of Python class-concept that give the possibility to combine a dictionary with associated functionality and you import the class from a module. In the setup-file you then after import of the class populate the dictionary with application parameter names and value and you make a short name for the associated function. This could be described in terms of "abstract datatype" if you like.
The start-up script now look like this:
from test_module3 import ParDict
p = {}
p['Y'] = 0.5
p['qSmax'] = 1.0
p['Ks'] = 0.1
parDict = ParDict('Test3', p)
par = parDict.parX
and the updated test_module3 is now somewhat more complex:
class ParDict(object):
""""Tool to associate a dictionary parDict with robustified way to
modifiy parameter values."""
def __str__(self):
return self.id
def __init__(self, id, parDict):
self.id = id
self.parDict = parDict
def parX(self, *x, **x_kwarg):
x_kwarg.update(*x)
x_temp = {}
for key in x_kwarg.keys():
if key in self.parDict.keys():
x_temp.update({key: x_kwarg[key]})
else:
print(key, 'seems not an accessible parameter')
self.parDict.update(x_temp)
Finally out in the Jupyter notebook you can now change parmeter values in parDict as before with simplified command-line par(Y=0.4, Ks=0.08) etc.
Answered By - janpeter Answer Checked By - Willingham (PHPFixing Volunteer)
0 Comments:
Post a Comment
Note: Only a member of this blog may post a comment.