0

I have a python function having a dataframe and parameters that is function1(df, 'A') or function1(df, 'A, B, C'). and I have 3 other functions FunctionA(df_A), FunctionB(df_B), FunctionC(df_C) df_A, df_B, df_C are arguments for dataframes passed from function1.

I need to call FunctionA if the passed argument in function1 is having value A, similary, FunctionB if the passed argument in function1 is having value B.

If all 3 values (A,B,C) are passed in Function1 then I need to execute the FunctionA then FunctionB then FunctionC in the same order and using the same dataframe. The dataframe returned from FunctionA will become input to FunctionB then input to FunctionC.

If the order of parameters are changed that is, if it (B,A,C) then, function1 will call FunctionB first, then the dataframe returned from FunctionB will become input to FunctionA then input to FunctionC, and finally will have o/p returned from FunctionC.

So, question is there an efficient way to handle it using python all the possible combinations of A,B,C or A,C,B or B,A,C or B,C,A or C,A,B or C,B,A ? I wanted to reduce the number of if statements to handle these cases. And if the number of arguments passed increased to 4 say A,B,C,D then if statements would explode to larger number. Is there a way to handle this scenario in efficient way? Please suggest.

functionA(df_A):
    print("inside A")
    # just for example I am doing something here
    df_A.reset_index(drop=True, inplace=True)
    return df_A

functionB(df_B):
    print("inside B")
    # just for example I am doing something here
    df_B.reset_index(drop=True, inplace=True)
    return df_B

functionB(df_C):
    print("inside C")
    # just for example I am doing something here
    df_C.reset_index(drop=True, inplace=True)
    return df_C

def function1(df, seq_abc):
    r = [x.strip().lower() for x in seq_abc.split(',')]
    if r[0] == 'A' and r[1] == 'B' and r[2] == 'C':
        df = functionA(df)
        df = functionB(df)
        df = functionC(df)
        print("A then B then C executed!")

    if r[0] == 'A' and r[1] == 'C' and r[2] == 'B':
        df = functionA(df)
        df = functionC(df)
        df = functionB(df)
        print("A then C then B executed!")

    if r[0] == 'B' and r[1] == 'C' and r[2] == 'A':
        df = functionB(df)
        df = functionC(df)
        df = functionA(df)
        print("B then C then A executed!")

returned_value = function1(df, "A,B,C") # the function1 will call FunctionA or B or C based on parameter passed.
print(returned_value)
  • 3
    Can you post the code for how you're doing it now? It's pretty hard to understand what you're trying to achieve from just the verbal description. – tzaman Jul 15 '21 at 11:18
  • First step: you'll want to break the string into a list of strings: e.g., `'A, B, C'` becomes`['A', 'B', 'C']`. – chepner Jul 15 '21 at 11:42
  • Does this answer your question? [Replacements for switch statement in Python?](https://stackoverflow.com/questions/60208/replacements-for-switch-statement-in-python) – MisterMiyagi Jul 15 '21 at 11:52
  • I have added the code @tzaman for reference, hope it helps to understand. – Ashvini Srivastava Jul 15 '21 at 12:05

1 Answers1

2

As often stated:

Python functions are first class citizen

So you could send an array with references to the functions to run

def function1(df, funcs):
    for f in funcs:
        f(df)

functions_to_run = [functionA, functionC]
function1(df, functions_to_run)

How you handle arguments depends on if the functions should have the same argument(s) or different. If the latter you could pass in partial functions with attached arguments.

An alternative to passing functions as arguments is to pass values and then have a dictionary within the function that maps the argument values to specific functions.

def function1(df, labels):

    func_map = {
      'A': functionA,
      'B': functionB,
      'C': functionC
    }

    for label in labels:
        func_map[label](df)

# Call with array of labels - in specific order
function1(df, ['A','C','B'])

# Since a string is iterable you could also do this
function1(df, 'ACB')

Same reasoning with arguments to the functions here. It all depends on what you want to achieve. Note that since

NLindros
  • 1,683
  • 15
  • 15