Reputation: 438
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
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
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
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
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