Hello, a question in the newsgroup got me thinking about the save use
of the ``savespace'' flag in modules, which should be used by third
party code.
Think of this function as an example:
def freezing(S,P):
"""Returns the freezing point temperature of seawater with a
salinity S and at a pressure P.
"""
TF=(-.0575+1.710523e-3*_A.sqrt(_A.absolute(S))-2.154996e-4*S)*S-7.53e-4*P
return TF
This looks simple and one wants to use the savespace flag for S and
P. So now the questions are rolling.
What if S or P are scalars?
Use asarray with the savespace flag. -> Error, this returns a copy
of the array and not a reference, which is bad for array arguments.
So use first asarray and then do asarray(S).savespace(1). Ok this
works for the function, but we need to reset the flag at the end of the
function. Also bad, what if S or P had the flag set before they
entered the function? Ok I have now build a class, which actually
keeps a record of these flags and has some helper methods to handle
this record. The example function looks now:
def freezing(S,P):
SP=mkspacesaver(S,P)
if not SP.isfloat():
raise ValueError, 'Arguments need to be of some float type'
TF=(-.0575+1.710523e-3*_A.sqrt(_A.absolute(S))-2.154996e-4*S)*S-7.53e-4*P
SP.free(); SP.clean(TF)
return TF
Note the test for float type, because if the user lazily entered an
integer array for e.g. the pressure, the then set savespace flag would
result in a very wrong answer. Although this seems to work for me, I
do not know if this really presents a solution, as I actually need to
put these lines into every similar function. The other way, to put the
coeff. into an array has also problems, as I first need to find out of
which type all arguments are and choose the highest one and it makes
it more difficult to follow the coeff. in the formula.
Any other suggestions, more general ways to handle argument testing?
Is the savespace flag only suited for more closed environments, where
one can assume more about the arguments?
Class attached,
__Janko
class mkspacesaver:
def __init__(self, *args):
"""Set for all arguments the savespace flag and make them to arrays.
Keep track of this. At the end of the function, all flags can be reset,
by a call to the method .free()
"""
self.refs = []
self.flags= []
for arg in args:
try:
arg.spacesaver()
ref = arg
except AttributeError:
ref = afuncs.asarray(arg)
self.flags.append(ref.spacesaver())
ref.savespace(1)
self.refs.append(ref)
def isfloat(self, index=None):
"""
Test if all refs have a float type, if a sequence is given
for index, only the indexed refs are tested.
"""
if index:
for i in index:
if not self.refs[i].typecode() in ('f','d'):
return 0
else:
for i in range(len(self.refs)):
if not self.refs[i].typecode() in ('f','d'):
return 0
return 1
def free(self):
for i in range(len(self.refs)):
self.refs[i].savespace(self.flags[i])
def clean(self, *args):
"""Test if the arguments have the savespace flag set and set it to zero.
Handle also scalars
"""
for arg in args:
try:
arg.savespace(0)
except AttributeError:
pass