I'm developing a toolbox containing several python scripts. For several of them some arguments may be numeric values. Depending of the script some may require a value v to be between -1 and 1, or 0 and 1 or 1 and 10 or ... An example could be a page width from an output diagram which should be always positive.
I can check all the time if v is in the required range. I could also for each of these range define an Action or a type using argparse. An example is given using a new type:
def positive_num(a_value):
"""Check a numeric positive."""
if not a_value > 0:
raise argparse.ArgumentTypeError("Should be positive.")
return a_value
And add it later to the parser:
parser_grp.add_argument('-pw', '--page-width',
help='Output pdf file width (e.g. 7 inches).',
type=positive_num,
default=None,
required=False)
Now, if the value is a correlation coefficient (or anything in a range) would it be possible using action or types to write something more general using:
def ranged_num(a_value, lowest=-1, highest=1):
"""Check a numeric is in expected range."""
if not (a_value >= lowest and a_value <= highest):
raise argparse.ArgumentTypeError("Not in range.")
return a_value
That could later be added like:
parser_grp.add_argument('-c', '--correlation',
help='A value for the correlation coefficient',
type=ranged_num(-1,1),
default=None,
required=False)
I have tried in several ways but whithout success.
Thank you
Per the documentation:
type=
can take any callable that takes a single string argument and returns the converted value
Therefore, to use it like type=ranged_num(-1,1)
, your ranged_num
function must return a function itself. A function that returns a function (or accepts a function as an argument, or both) is often referred to as a "higher-order function".
Here's a minimal example:
def ranged_num(lowest=-1, highest=1):
"""Check a numeric is in expected range."""
def type_func(a_value):
a_value = int(a_value) # or "float"; you could also have error handling here
if not (a_value >= lowest and a_value <= highest): # I'd rewrite this to an "or"
raise argparse.ArgumentTypeError("Not in range.")
return a_value
return type_func
Now ranged_num
creates and returns a function, type_func
, that is responsible for handling the string coming from the command line.