考虑下面的代码:为什么用一个不可迭代的参数解链一个链会引发这个错误?
from itertools import chain list(chain(42))
我传递一个非迭代器作为参数传递给
chain
和小奇怪的是,我得到的正是这种错误:TypeError: 'int' object is not iterable
(传递到
list
仅仅是必要的,因为chain
在实际迭代之前不会评估它的参数。)如果我正确地使用
chain
,我可以解压结果作为函数的参数:from itertools import chain foo = lambda x: x foo(*chain([42]))
这将运行没有错误。
现在,考虑的上述两种情况的组合,即,与非可迭代参数链解压作为函数参数:
from itertools import chain foo = lambda x: x foo(*chain(42))
正如预期的那样,这将失败。在Python 3中,这会引发与第一种情况相同的错误。然而,在Python 2.7.12中,抛出的错误是:
TypeError: <lambda>() argument after * must be an iterable, not itertools.chain
这对我没有任何意义。明显是可迭代类型:
isinstance(chain(42),collections.Iterable)
产量为True
。另外,它在第二个例子中没有引起任何问题。我期望类似于错误消息2或Python 3中的错误消息。此错误消息的解释是什么?
0
A
回答
0
您所看到的行为是企图给什么地方发生了错误的函数调用更清晰的错误消息。
Python 2.7确定对象是否可迭代的方法是试图迭代它,然后在必要时捕获TypeError
异常。它实际上并未在Python代码中实现,但这仍然是处理函数调用语法时发生的事情。 注意:这与lambda
没有任何关系,普通的旧的def
也可以说明这个例子。
函数调用在CPython的2.7 this C code处理:
static PyObject *
ext_do_call(PyObject *func, PyObject ***pp_stack, int flags, int na, int nk)
{
... snip ...
t = PySequence_Tuple(stararg);
if (t == NULL) {
if (PyErr_ExceptionMatches(PyExc_TypeError) &&
/* Don't mask TypeError raised from a generator */
!PyGen_Check(stararg)) {
PyErr_Format(PyExc_TypeError,
"%.200s%.200s argument after * "
"must be an iterable, not %200s",
PyEval_GetFuncName(func),
PyEval_GetFuncDesc(func),
stararg->ob_type->tp_name);
}
goto ext_call_fail;
... snip ...
}
我已经被截断的代码简洁,以显示相关的块:在starargs进行迭代成一个元组,如果失败与PyExc_TypeError
那么随着类型和消息匹配你所看到的,会引发一个新的错误。
在Python 3中,函数调用C代码被清理并显着简化。其实ext_do_call
函数甚至不存在,它可能在执行PEP 3113时被删除。现在来自迭代断链的异常冒泡未处理。如果您想在当前的通话代码中进行搜索,您可以开始使用Python/ceval.c::do_call_core
进行挖掘。
相关问题
- 1. 为什么这段代码会生成一个链接?
- 2. 为什么迭代一个很大的std :: list会这么慢?
- 3. 为什么这个jQuery.ajax不会引发错误?
- 4. 为什么这个可迭代的实现会产生一个stackoverflow?
- 5. 这个函数为什么会抛出一个错误?
- 6. 这个函数为什么会抛出一个过滤错误?
- 7. 为什么这会产生一个错误 - 一个鬼NSArray?
- 8. TypeError:'NoneType'对象不可迭代。为什么我会得到这个错误?
- 9. 为什么这不是一个有效的链接函数?
- 10. 为什么这个'验证'方法会引发一个ArgumentError?
- 11. 为什么不是这个库链接一个编译指示?
- 12. 为什么这个链接不再打开一个文件?
- 13. 这段代码为什么会产生一个错误?
- 14. 不知道为什么我得到一个链接错误
- 15. 为什么这个变量赋值会引发错误?
- 16. 为什么这个MySQL语句会引发语法错误?
- 17. 为什么这个VBScript会给我一个错误?
- 18. 为什么这个Javascript会抛出一个错误?
- 19. 为什么这个wxPython/PyOpenGL代码在glPushMatrix上引发错误?
- 20. 为什么这个C#代码踢出一个错误?
- 21. 为什么Oracle不会在这里抛出一个错误
- 22. 为什么这段代码不会在JavaScript中引发错误?
- 23. 为什么我得到一个对象不是可迭代错误?
- 24. JSON.parse上一个数字作为一个字符串不会引发错误
- 25. 为什么链接器在这里不会产生多个定义错误?
- 26. C++:为什么取消引用这个向量迭代器段错误?
- 27. 为什么我得到这个错误“TypeError:'方法'对象不可迭代”?
- 28. 这个错误是什么,为什么会发生?下面
- 29. 为什么Sass可变参数会引发错误?
- 30. 为什么会出现这个错误?
另外值得注意的是,在您尝试迭代结果之前,'chain(42)'不会在Python2中引发错误。 – iafisher
@iafisher:这就是为什么我在它周围包裹了'list'的原因。另请参阅我的编辑。 – Wrzlprmft
*'itertools.chain'是一个可迭代的类型* < - 只有当您通过迭代才能通过。垃圾进垃圾出。 – wim