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.