[SOLVED] How to define multiple functions in single function declaration?

Issue

In Fortran you can do something like this:

#:for DTYPE, NAME in [('real','ssygvd'), ('dble', 'dsygvd'), ('cmplx', 'chegvd')]

  subroutine ${DTYPE}$_something_${NAME}$(args)
  [some commands]
  end subroutine ${DTYPE}$_something_${NAME}$

Can something like this be done in Python?

I want to write a function like this for float, int and str.

def get_int_tuple(value):
   try:
       values = [int(i) for i in value.split(',')]
       assert len(values) in range(1,4)
   except (ValueError, AssertionError):
       raise argparse.ArgumentTypeError(
           'Provide a CSV list of 1 up to 3 integers'
       )

   # return our value as is if there is only one
   if len(values) == 1:
       return tuple(np.array(values))

   # if there are three - return a range
   return tuple(np.arange(*values))

Which I will then pass to the parser:

parser.add_argument(
    "--kernel",
    type=get_str_tuple,
    help="SVM kernel. Options: 'linear', 'poly', 'rbf' (default=rbf)"
)

parser.add_argument(
    '--c',
    type=get_float_tuple,
    help="C (hyper)parameter of 'rbf' kernel (default=0.05)."
)

parser.add_argument(
    '--degree',
    type=get_int_tuple,
    help="Degree of the 'poly' kernel. (default=3)."
)

Solution

The types themselves are first-class objects, so you can pass them as arguments to a single function.

First, define a function that defines the common function, closing over the desired type.

def make_type(type_, type_name):
    def get_tuple(value):
       try:
           values = [type_(i) for i in value.split(',')]
           assert len(values) in range(1,4)
       except (ValueError, AssertionError):
           raise argparse.ArgumentTypeError(
               f'Provide a CSV list of 1 or 3 {type_name}'
           )
    
       # return our value as is if there is only one
       if len(values) == 1:
           return tuple(np.array(values))
    
       # if there are three - return a range
       return tuple(np.arange(*values))
    return get_tuple
            

Then use make_type to create the necessary argument for the type argument to `add_argument.

parser.add_argument(
    "--kernel",
    type=make_type(str, "strings"),
    help="SVM kernel. Options: 'linear', 'poly', 'rbf' (default=rbf)"
)

parser.add_argument(
    '--c',
    type=make_type(float, "floating-point values"),
    help="C (hyper)parameter of 'rbf' kernel (default=0.05)."
)

parser.add_argument(
    '--degree',
    type=make_tuple(int, "integers"),
    help="Degree of the 'poly' kernel. (default=3)."
)

Answered By – chepner

Answer Checked By – Senaida (BugsFixing Volunteer)

Leave a Reply

Your email address will not be published.