I was looking for an algorithm capable of storing and running functions with a flexible number of arguments. I ended up finding a switch/case analogue for python which meets my requirements:
def opA_2(x, y):
return x - y
def opB_3(x, y, z):
return x + y - z
def opC_2(x, y):
return x * y
def opD_3(x, y, z):
return x * y + z
op_dict = {'opA_2': opA_2,
'opB_3': opB_3,
'opC_2': opC_2,
'opD_3': opD_3
}
op_lambda_dict = {'opA_2': lambda x, y, kwargs: op_dict['opA_2'](x, y),
'opB_3': lambda x, y, kwargs: op_dict['opB_3'](x, y, kwargs['z']),
'opC_2': lambda x, y, kwargs: op_dict['opC_2'](x, y),
'opD_3': lambda x, y, kwargs: op_dict['opD_3'](x, y, kwargs['z']),
}
def dispatch_op(func_dict, op, x, y, **kwargs):
return func_dict.get(op, lambda a, b, c: None)(x, y, kwargs)
coefs_dict = {'i': 1, 'j': 2, 'k': 3, 'z': 4}
print('Original lambda dict result:', dispatch_op(op_lambda_dict, 'opB_3', 1, 2, **coefs_dict))
Resulting in:
Original lambda dict result: -1
Once I implemented this structure to my target code, however, I encountered many issues because my operations are defined via a loop.
As far as I understand it, this is because the lambda functions are not initialised, and they end up pointing to the last operation declared.
This additional code reproduces the issue:
op_looplambda_dict = {}
for label, func in op_dict.items():
if '2' in label:
op_looplambda_dict[label] = lambda x, y, kwargs: func(x, y)
if '3' in label:
op_looplambda_dict[label] = lambda x, y, kwargs: func(x, y, kwargs['z'])
print('Loop lambda dict result:', dispatch_op(op_looplambda_dict, 'opB_3', 1, 2, **coefs_dict))
Resulting in:
Loop lambda dict result: 6
This is the result of opD_3
instead of opB_3
I wonder if anyone could please offer any advice, on how to properly declare the lambda functions in the second case or a different code structure to avoid it. Thanks a lot.