Function calling conventions

I have a quick question regarding the order in which funcitons are/should be called.

Is there a preferred convention, or can issues arise from, using a “controller function”?

By controller, I mean this:

def func_order():
    ''' function to determine call order of functions; called here so this
        function can be looped within main() '''
    
    text = fi_get()       
    letter = letter_get()
    fi_srch(text, letter)

# function main()
def main():
    ''' call func_order within loop so user can search multiple times '''
    hi_user()
    func_order()
    
    while True: 
        y_n = input("Enter 'r' to restart search, 'x' to exit program: ")
        if y_n.casefold() == "x": 
            print("Goodbye!")
            break
        elif y_n.casefold() == "r":  # restart to search again
            func_order()             # in effect, restart program 
        else:  # if invalid, reprompt
            print("Invalid. Enter a valid option.")

if __name__ == "__main__":
    main()

I know it could be looped from within main(), but to my mind, it seems more organized this way. Is there a term for this? Or should I avoid this kind of call ordering? I only ask because I haven’t seen it done it before.

I have a quick question regarding the order in which funcitons
are/should be called.
Is there a preferred convention, or can issues arise from, using a
“controller function”?

By controller, I mean this:

def func_order():
   ''' function to determine call order of functions; called here so this
       function can be looped within main() '''

   text = fi_get()
   letter = letter_get()
   fi_srch(text, letter)

Do you mean that this function performs some slightly higher level
operation using the correct order and usage of the functions it calls?

Yes, this is entirely fine and very normal: the purpose of a function
is to perform some higher level operation built from lower order things.
The function is “higher order” entirely because it orchestrates these
other things.

In fact, this is often the best way to do things. If you give the
function a good descriptive name, then your main function which calls it
is immediately much easier to understand.

So your example main programme:

 # function main()
 def main():
     ''' call func_order within loop so user can search multiple times '''
     hi_user()
     func_order()
     while True:
         y_n = input("Enter 'r' to restart search, 'x' to exit program: ")
         if y_n.casefold() == "x":
             print("Goodbye!")
             break
         elif y_n.casefold() == "r":  # restart to search again
             func_order()             # in effect, restart program
         else:  # if invalid, reprompt
             print("Invalid. Enter a valid option.")

If you renamed func_order to, say, restart, then your main loop is
now just the main control flow, with the functions, of which you might
have several, encapsulating the specific actions required.

I know it could be looped from within main(), but to my mind, it
seems more organized this way. Is there a term for this? Or should I
avoid this kind of call ordering? I only ask because I haven’t seen it
done it before.

You’re correct, it is more organised and very much a good thing to do.

In fact, you’re on your way to classes: an object whose attribute
represent the state of something you’re doing or controlling, and
methods being functions effectively called on the object to do
particular well defined and well named things. From the outside the
calling code just asks the object to do “something”, and needs no
special knowledge of how it is done.

The class describes how your “controller” works, and an instance of the
class is a controller perhaps for a particular thing. There isn’t enough
stuff in your example above to make a detailed example (for example,
I’ve no idea what fi_get and hi_user etc do). But…

Made up untested example:

 class Controller:

     def __init__(self, user_name):
         # set whatever attributes are needs to track the state
         # much as you'd set global variable in a tiny programme
         self.user_name = user_name

     def hi(self):
         print("Hi", self.user_name)

     def read_text(self):
         self.text = input("Enter some text: ")

     def read_letter(self):
         self.letter = input("Enter a letter: ")

     def reset(self):
         ... reset the text and letter ...
         self.read_text()
         self.read_letter()
         fi_search(self.text, self.letter)

and your main programme might then read a bit like this:

 # function main()
 def main():
     ''' call func_order within loop so user can search multiple times '''
     controller = Controller("User Name Here")
     controller.hi()
     controller.reset()
     while True:
         y_n = input("Enter 'r' to restart search, 'x' to exit program: ")
         if y_n.casefold() == "x":
             print("Goodbye!")
             break
         elif y_n.casefold() == "r":  # restart to search again
             controller.reset()
         else:  # if invalid, reprompt
             print("Invalid. Enter a valid option.")

It doesn’t make complete sense because I’m just inventing the stuff you
actually want to do.

Cheers,
Cameron Simpson cs@cskk.id.au

Thank you for the reply.

I see. So in a sense, I’m combining lower processes into higher, automated processes.

In my first draft, I had named it exactly that. I will change it back.

For example:

def powers(x1, x2):
    y = pow(x1, x2)
    return y
def main():
    powers()
main()

So, one could say that in the same way a functional relationship exists between pow(x1, x2) and its output y, it itself becomes a lower order process acting as input x for def powers(). Then, within a class, controller.powers(x1, x2) the powers(x1, x2) becomes lower order process, functionally related to the class as an input, becoming x in terms of f (with f a process defined by the class).

I’m not sure if I’m saying that clearly, I’m just trying to describe it mathematically. Thanks again for the help. I will start practicing with classes.

1 Like