Python map emptied after using tuple or iteration
Question:
The following code does not print anything from the for
loop; it only prints the result of the tuple
. This is very unintuitive because I haven’t explicitly modified the cheapest
map, yet it behaves as if it is empty after calling tuple
.
So, what’s going on?
store1 = [10.00, 11.00, 12.34, 2.34]
store2 = [9.00, 11.10, 12.34, 2.01]
cheapest = map(min, store1, store2)
print(tuple(cheapest))
for v in cheapest:
print(v)
Expected output:
(9.0, 11.0, 12.34, 2.01)
9.0
11.0
12.34
2.01
Actual output:
(9.0, 11.0, 12.34, 2.01)
If I run the for
loop first, then the behavior is reversed: the for
loop prints the values from the cheapest
map and the print(tuple(cheapest))
result is empty as in:
Actual output (order reversed):
9.0
11.0
12.34
2.01
()
Answers:
When learning Python you’ll need to pay close attention to the return type of various functions, as many, like map
, actually return an iterator1.
While an iterator can be efficient as it is only evaluated if necessary, it can lead to confusion like this where your data is suddenly "gone".
If you need to capture that result before using it in multiple locations, convert it into a more permanent form, like:
cheapest = list(map(min, store1, store2))
Where that can still be used in a for
since it’s iterable.
1 In Ruby this is like map { ... }.lazy
being enabled by default. In Rust it’s very similar to Python, a map()
must be captured with collect()
before it’s anything other than an iterator. If you’re used to things like JavaScript where it just dumps out an array, it’ll require a bit of re-learning.
The following code does not print anything from the for
loop; it only prints the result of the tuple
. This is very unintuitive because I haven’t explicitly modified the cheapest
map, yet it behaves as if it is empty after calling tuple
.
So, what’s going on?
store1 = [10.00, 11.00, 12.34, 2.34]
store2 = [9.00, 11.10, 12.34, 2.01]
cheapest = map(min, store1, store2)
print(tuple(cheapest))
for v in cheapest:
print(v)
Expected output:
(9.0, 11.0, 12.34, 2.01)
9.0
11.0
12.34
2.01
Actual output:
(9.0, 11.0, 12.34, 2.01)
If I run the for
loop first, then the behavior is reversed: the for
loop prints the values from the cheapest
map and the print(tuple(cheapest))
result is empty as in:
Actual output (order reversed):
9.0
11.0
12.34
2.01
()
When learning Python you’ll need to pay close attention to the return type of various functions, as many, like map
, actually return an iterator1.
While an iterator can be efficient as it is only evaluated if necessary, it can lead to confusion like this where your data is suddenly "gone".
If you need to capture that result before using it in multiple locations, convert it into a more permanent form, like:
cheapest = list(map(min, store1, store2))
Where that can still be used in a for
since it’s iterable.
1 In Ruby this is like map { ... }.lazy
being enabled by default. In Rust it’s very similar to Python, a map()
must be captured with collect()
before it’s anything other than an iterator. If you’re used to things like JavaScript where it just dumps out an array, it’ll require a bit of re-learning.