Opps_0
Opps_0

Reputation: 438

How to call multiple functions using loop?

My program structure is given below

def method_1(new_parameters):
    ...

def method_2(new_parameters):
    ...

def calculation(parameters):
    ......
    new_parameters = generate_new_params
    method_call = method_1(**new_parameters)

if __name__ =="__main__":
    ......
    output = calculation(parameters)

The code is working fine. I have to run the program 2 times to get the output based on 2 methods. First, I run the program using method_1(**new_parameters) and second time method_2(**new_parameters).

If I want to call both methods one after another (maybe using loop) then how I have to write the code?

Say for example,

if __name__ =="__main__":
    Methods = {"method-1": method_1, "method-2": method_2}
    ......
    for method in Methods:
        output = calculation(parameters)

I have gone through some posts (this and this) but not getting any idea. Here, the challenge for me to call the function from def calculation() but I have to pass the function from main.

Upvotes: 1

Views: 2248

Answers (4)

Disgusting
Disgusting

Reputation: 123

It seems as though you want a way to iterate over a collection of functions without too much complicated code.

I would suggest making a class that bundles all the methods together like so:

class Calculator():
    """Container class for functions over which to iterate and/or access with strings."""
    def __init__(self):
        pass

    def list_calc_funcs(self):
        """returns list of functions starting with 'calc_', uncalled"""
        return [getattr(self, name) for name in self.list_calc_names()]

    def list_calc_names(self):
        """returns list of unique part of strings identifying 'calc_' functions"""
        return [string for string in dir(self) if string[:5]=='calc_']

    def calculate(self,cnt:str,*args,**kwargs):
        """calls a 'calc_' function using a string"""
        try:
            calc = getattr(self,"calc_" + cnt)
        except AttributeError:
            raise ValueError("The named function does not exist.")
        return calc(*args,**kwargs)

    def calc_foo(self,*args,**kwargs):
        pass

    def calc_bar(self,*args,**kwargs):
        pass

    def calc_1(self,*args,**kwargs):
        pass

    def calc_2(self,*args,**kwargs):
        pass

C = Calculator()

The way this works is by taking advantage of "dir()" and "getattr()". dir() basically returns a list with all the names of instance variables, including any functions. For instance, if you called dir(C) it would return:

['__class__',
 '__delattr__',
 '__dict__',
 '__dir__',
 '__doc__',
 '__eq__',
 '__format__',
 '__ge__',
 '__getattribute__',
 '__gt__',
 '__hash__',
 '__init__',
 '__init_subclass__',
 '__le__',
 '__lt__',
 '__module__',
 '__ne__',
 '__new__',
 '__reduce__',
 '__reduce_ex__',
 '__repr__',
 '__setattr__',
 '__sizeof__',
 '__str__',
 '__subclasshook__',
 '__weakref__',
 'calc_1',
 'calc_2',
 'calc_bar',
 'calc_foo',
 'calculate',
 'list_calc_funcs',
 'list_calc_names']

This lets you use basic string methods to find the methods you want by simply "tagging" them with whatever naming scheme takes your fancy.

getattr(object,attribute_name) is an incredibly useful one to know and it allows you to access properties/variables/methods of pretty much anything using strings. Its very powerful if you need to give the user the ability to specify a function based on a string, or if you need to iterate over some values in dir().

In list_calc_names() I use a list comprehension to easily return all the names of attributes starting with "calc_". Note that if you do this you need to make sure you don't start any variable names that way or they will be returned too. In my case it returns:

['calc_1', 'calc_2', 'calc_bar', 'calc_foo']

In list_calc_funcs() I use a list comprehension again to iterate over the result of list_calc_names() and return the functions themselves. It returns:

[<bound method Calculator.calc_1 of <__main__.Calculator object at 0x000000000A12E0D0>>,
 <bound method Calculator.calc_2 of <__main__.Calculator object at 0x000000000A12E0D0>>,
 <bound method Calculator.calc_bar of <__main__.Calculator object at 0x000000000A12E0D0>>,
 <bound method Calculator.calc_foo of <__main__.Calculator object at 0x000000000A12E0D0>>]

The function "calculate()" shows how you might generalise calling specific functions based on strings that can be input at runtime rather than by calling the function directly.

Upvotes: 0

Matthew Barlowe
Matthew Barlowe

Reputation: 2328

I would just pass the function as a parameter to the calculation function like so:

def method_1(new_parameters):
    ...

def method_2(new_parameters):
    ...

def calculation(parameters, method_name, method):
    ......
    new_parameters = generate_new_params
    method_call = method(**new_parameters)

if __name__ =="__main__":
    ......
    output = calculation(parameters)

and then do your loop like this:

if __name__ =="__main__":
    Methods = {"method-1": method_1, "method-2": method_2}
    ......
    for key, value in Methods.items():
        output = calculation(parameters, key, value)

Upvotes: 0

user1101221
user1101221

Reputation: 414

I can't understand your question clearly, but I can guess.

Try this.

def calculation(mt, parameters):
    ......
    new_parameters = generate_new_params
    method_call = mt(**new_parameters)

if __name__ =="__main__":
    Methods = {"method-1": method_1, "method-2": method_2}
    ......
    
    outputs = [calculation(method, parameters) for key, method in Methods.items()]

Upvotes: 1

CallMePhil
CallMePhil

Reputation: 1657

Are you referring to passing a function as a parameter to another one and then calling it? That is referred to as a higher order function. So something like this.

def method_1(new_parameters):
    ...

def method_2(new_parameters):
    ...

def calculation(parameters, callback):
    ......
    new_parameters = generate_new_params
    callback_result = callback(**new_parameters)

if __name__ =="__main__":
    ......
    output1 = calculation(parameters, method_1)
    output2 = calculation(parameters, method_2)

Upvotes: 0

Related Questions