繁体   English   中英

为什么解开带有不可迭代参数的链会引发此错误?

[英]Why does unpacking a chain with a non-iterable argument raise this error?

  1. 考虑以下代码:

     from itertools import chain list(chain(42)) 

    我将一个不可迭代的参数传递给chain并且毫不奇怪,我得到了这个错误:

     TypeError: 'int' object is not iterable 

    (仅因为chain在实际迭代之前才评估其参数,所以传递到list是唯一必要的。)

  2. 如果正确使用chain ,则可以将结果作为函数参数解压缩:

     from itertools import chain foo = lambda x: x foo(*chain([42])) 

    这没有错误运行。

  3. 现在,考虑以上两种情况的组合,即,具有不可迭代参数的链被解压缩为函数参数:

     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 

    这对我来说没有任何意义。 itertools.chain显然是一个可迭代的类型: isinstance(chain(42),collections.Iterable)产生True 同样,在第二个示例中它也没有引起任何问题。 我期望与情况2或Python 3类似的错误消息。此错误消息的解释是什么?

您看到的行为是试图给出更清晰的错误消息,说明函数调用出了什么问题。

Python 2.7确定对象是否可迭代的方法只是尝试对其进行迭代,然后在必要时捕获TypeError异常。 它实际上并没有在Python代码中实现,但这仍然是处理函数调用语法时发生的事情。 注意:这与lambda无关,一个普通的def也将说明该示例。

这个C代码在CPython 2.7中处理了函数调用:

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM