Python3:内置函数“map”有错误吗?

Tak*_*oka 4 python behavior built-in python-3.x map-function

以下是我使用 Python 3.8.1(在 macOS Mojave、10.14.6 上,以及在其他一些平台上的 Python 3.7(或较旧版本))。我是计算新手,不知道如何请求改进语言,但我认为我发现了内置函数的奇怪行为map

随着代码的next(iter(()))提高,我期望从以下代码中StopIteration得到:StopIteration

tuple(map(next, [iter(())]))

令我惊讶的是,这默默地返回了元组()

StopIteration因此,当命中返回next的“空”迭代器时,地图对象的解包似乎停止了 iter(())。但是,我认为异常处理不正确,因为StopIteration在从列表中选择“空”迭代器(被 命中next)之前没有引发异常。

  1. 我对这种行为的理解正确吗?
  2. 这种行为是有意为之吗?
  3. 这种情况在不久的将来会改变吗?或者我怎样才能得到它?

编辑:如果我以不同的方式解包地图对象,例如 by list、 for 循环、在列表中解包、解包函数参数、 by set、 ,则行为类似dict。所以我相信这不是tuple,但这map是错误的。

编辑:实际上,在 Python 2 (2.7.10) 中,“相同”代码会引发 StopIteration. 我认为这是理想的结果(除了map在这种情况下不返回迭代器)。

use*_*ica 5

这不是一个map错误。这是 Python 决定依赖异常来控制流的丑陋后果:实际的错误看起来像正常的控制流。

map跟注nextiter(())next加注StopIteration。这会在调用中StopIteration传播。这看起来像通常会发出信号以表示地图结束的信号,因此认为地图根本没有元素。map.__next__tupleStopIterationStopIterationmap.__next__tuple

这会导致比你所看到的更奇怪的后果。例如,map当映射函数引发异常时,迭代器不会将自身标记为已耗尽,因此您甚至可以在之后继续迭代它:

m = map(next, [iter([]), iter([1])])

print(tuple(m))
print(tuple(m))
Run Code Online (Sandbox Code Playgroud)

输出:

()
(1,)
Run Code Online (Sandbox Code Playgroud)

(CPythonmap实现实际上没有办法将自身标记为耗尽 - 它依赖于底层迭代器。)

这种 StopIteration 问题非常烦人,他们实际上改变了生成器 StopIteration 处理来缓解它。StopIteration 过去通常从生成器中正常传播,但现在,如果 StopIteration 从生成器中传播,它会被 RuntimeError 替换,因此生成器看起来不像正常结束。但这仅影响生成器,而不影响其他迭代器,例如map.