I get different output when using a list comprehension versus a generator comprehension. Is this expected behavior or a bug?
Consider the following setup:
To see what's going on, replace c[k] with a function with a side effect:
def f(c,k):
print(c,k)
return c[k]
print("listcomp")
print(list(zip(*( [f(c,k) for k in unique_keys] for c in all_configs))))
print("gencomp")
print(list(zip(*( (f(c,k) for k in unique_keys) for c in all_configs))))
output:
listcomp
{'a': 1, 'b': 3} a
{'a': 1, 'b': 3} b
{'a': 2, 'b': 2} a
{'a': 2, 'b': 2} b
[(1, 2), (3, 2)]
gencomp
{'a': 2, 'b': 2} a
{'a': 2, 'b': 2} a
{'a': 2, 'b': 2} b
{'a': 2, 'b': 2} b
[(2, 2), (2, 2)]
c in generator expressions is evaluated after the outer loop has completed:
c bears the last value it took in the outer loop.
In the list comprehension case, c is evaluated at once.
(note that aabb vs abab too because of execution when zipping vs execution at once)
note that you can keep the "generator" way of doing it (not creating the temporary list) by passing c to map so the current value is stored:
print(list(zip(*( map(c.get,unique_keys) for c in all_configs))))
in Python 3, map does not create a list, but the result is still OK: [(1, 2), (3, 2)]