map()我发现了一种使用不等同于列表理解的情况。next当用作第一个参数时会发生这种情况。
例如:
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
Run Code Online (Sandbox Code Playgroud)
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
Run Code Online (Sandbox Code Playgroud)
任何其他异常都会按其应有的方式发生。例子:
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
Run Code Online (Sandbox Code Playgroud)
看起来很奇怪。它与 Python 3.9 和 Python 3.11 的工作方式相同。
看起来像map()这样工作:
def map(func, iterator):
try:
while True:
item = next(iterator)
yield func(item)
except StopIteration:
pass
Run Code Online (Sandbox Code Playgroud)
但我希望它能像这样工作:
def map(func, iterator):
while True:
try:
item = next(iterator)
except StopIteration:
break
yield func(item)
Run Code Online (Sandbox Code Playgroud)
这是一个错误吗?
尝试next致电map:
>>> >>> m = map(next, iterators)
>>> next(m)
1
>>> next(m)
'hello'
>>> next(m)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
Run Code Online (Sandbox Code Playgroud)
它可以list看到StopIteration并使用它来停止根据收益构建列表map。
另一方面,列表理解是通过迭代 来构建列表,而不是列表iterators中的特定迭代器。也就是说,用于为列表生成一个值,而不是确定我们是否已到达 的末尾。next(it)iterators