簡體   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