I found a case when map()
usage isn't equivalent to a list comprehension. It happens when next
used as the first argument.
For example:
l1 = [1, 2]
l2 = ['hello', 'world']
iterators = [iter(l1), iter(l2)]
# list comprehension
values1 = [next(it) for it in iterators]
# values1 = [1, "hello"]
values2 = [next(it) for it in iterators]
# values2 = [2, "world"]
values3 = [next(it) for it in iterators]
# raise StopIteration
l1 = [1, 2]
l2 = ['hello', 'world']
iterators = [iter(l1), iter(l2)]
# map
values1 = list(map(next, iterators))
# values1 = [1, "hello"]
values2 = list(map(next, iterators))
# values2 = [2, "world"]
values3 = list(map(next, iterators))
# values3 = []
# doesn't raise StopIteration
Any other exceptions occur as they should. Example:
def divide_by_zero(value: int):
return value // 0
l = [1, 2, 3]
values = list(map(divide_by_zero, l))
# raises ZeroDivisionError as expected
values = [divide_by_zero(value) for value in l]
# raises ZeroDivisionError as expected, too
It seems very strange. It works the same with Python 3.9 and Python 3.11.
It seems like map()
works like this:
def map(func, iterator):
try:
while True:
item = next(iterator)
yield func(item)
except StopIteration:
pass
but I expected it to work like this:
def map(func, iterator):
while True:
try:
item = next(iterator)
except StopIteration:
break
yield func(item)
Is it a bug?