I am expecting a logic table like output and I do get this output if I convert the settings dict to str first:
with settings = str(settings)
I get
[  
"{'l1': 0, 'lp1': **0**}",   
"{'l1': 0, 'lp1': **1**}",   
"{'l1': 1, 'lp1': **0**}",   
"{'l1': 1, 'lp1': **1**}"]
This is a simplified code block that exhibits the same behaviour
l_params = {
    "l1": [0,1]
}
lp_params = {
    "lp1": [0,1]
}
def grid_parameters(parameters: dict[str, Iterable[Any]]) -> Iterable[dict[str, Any]]:
    for params in product(*parameters.values()):
        yield dict(zip(parameters.keys(), params))
outlist = []
for l_settings in grid_parameters(l_params):
    for lp_settings in grid_parameters(lp_params):
        settings = l_settings
        settings['lp1'] = lp_settings['lp1']
        outlist.append(settings)
        print('ls', outlist)
with this I get:
[  
{'l1': 0, 'lp1': **1**},   
{'l1': 0, 'lp1': **1**},  
{'l1': 1, 'lp1': **1**},  
{'l1': 1, 'lp1': **1**}]
If I print out outlist in each iteration we see that the correct data is appended, but in the next iteration that data has been change?
ls [{'l1': 0, 'lp1': **0**}]  
ls [{'l1': 0, 'lp1': **1**}, {'l1': 0, 'lp1': 1}]  
ls [{'l1': 0, 'lp1': 1}, {'l1': 0, 'lp1': 1}, {'l1': 1, 'lp1': **0**}]  
ls [{'l1': 0, 'lp1': 1}, {'l1': 0, 'lp1': 1}, {'l1': 1, 'lp1': **1**}, {'l1': 1, 'lp1': 1}]  
I have used the cast to str, to get around this but it would be really cool to understand why this is happening?
 
    