TL;DR Is a docstring supposed to be writable as simply as
x.__doc__ = 'string' ?
It seems to work in 3.5.2.
I've written function for taking and checking GUI keyboard inputs. It's here on Code Review if anybody needs the details.
A fundamental part of it is the ability for it to use supplied checking functions, to check whether the input strings are valid in any given context. For better or worse, I decided to use the check function docstring to supply help information to the GUI, which would then parse it, as it was easy to do.
This is an example, the 'pair of floats' check function, the encoding of the help hints into the docstring is fairly obvious.
def float_pair(in_str):
"""[f,f] Two floats separated by a comma
[end_help]
in_str input string which should represent float, float
raise ValueError if that's not true
return a list of the two values
"""
fields = in_str.split(',')
if len(fields) != 2:
raise ValueError('need two floats separated by one comma')
output = [float(f) for f in fields]
return output
I now want to add a capability to check whether a float is in a certain range, ideally passing that range to a check function factory. Ideally the docstring of the returned function will contain the range, so that the help the GUI gives is relevant. I therefore need to set the docstring at run time.
A lot of searching has left me confused about whether a docstring is supposed to be writable or not. I've seen this question. Unfortunately, I'm only a physicist turned programmer, not a skilled metaprogrammer, so I don't understand the finer points.
So I tried it in the simplest possible way, and it seems to work, at least on python 3.5.2. I'm going to up-version eventually, if for no more than f strings. My concern is whether it's intended to keep working in future releases, or whether it will be 'fixed' to readonly.
def float_range_factory(x, y):
def float_range(z):
fz = float(z)
if x<=fz<y:
return fz
raise ValueError('input {} must be in the interval [{}, {}]'.format(z, x, y))
float_range.__doc__ = '[f range] Return float in the interval [{}, {}]'.format(x, y)
return float_range