I get different output when using a list comprehension versus a generator comprehension. Is this expected behavior or a bug?
Consider the following setup:
This is happening because zip(*) call resulted in evaluation of the outer generator and this outer returned two more generators.
(c[k], print(c)) for k in unique_keys)
The evaluation of outer generator moved c to the second dict: {'a': 2, 'b':2}.
Now when we are evaluating these generators individually they look for c somewhere, and as its value is now {'a': 2, 'b':2} you get the output as [(2, 2), (2, 2)].
Demo:
>>> def my_zip(*args):
... print(args)
... for arg in args:
... print (list(arg))
...
... my_zip(*((c[k] for k in unique_keys) for c in all_configs))
...
Output:
# We have two generators now, means it has looped through `all_configs`.
(. at 0x104415c50>, . at 0x10416b1a8>)
[2, 2]
[2, 2]
The list-comprehension on the other hand evaluates right away and can fetch the value of current value of c not its last value.
c?Use a inner function and generator function. The inner function can help us remember c's value using default argument.
>>> def solve():
... for c in all_configs:
... def func(c=c):
... return (c[k] for k in unique_keys)
... yield func()
...
>>>
>>> list(zip(*solve()))
[(1, 2), (3, 2)]