繁体   English   中英

为什么“扩展可迭代解包”不适用于空字符串?

[英]Why is 'Extended Iterable Unpacking' not working for empty strings?

为什么是

>>> a, *b = '' 

不可能,当

>>> a, *b = ' '
>>> a, b
(' ', [])  # b == empty list here anyway.

>>> type('')
<class 'str'>

我的意思是,为什么不是

>>> a, *b = ''
>>> a, b  # a could == ''
('', [])

因为指定了一个强制变量。

右侧应该至少有一项(字符串一个字符)。


根据PEP-3131

简单赋值左侧的元组(或列表)(未为扩充赋值定义解包)最多可以包含一个带有单个星号的表达式(此后称为“加星号”表达式,而其他表达式在该列表称为“强制性” )。 这指定了一个子表达式,该子表达式将被分配一个列表,该列表包含未分配给任何强制表达式的可迭代对象的所有项目,如果没有此类项目,则为空列表。

基于PEP 3132

功能unpack_iterable()ceval.c被改变来处理扩展拆包,经由argcntafter参数。 在 UNPACK_EX 情况下,该函数将执行以下操作:

  • 在加星之前收集强制性目标的所有项目
  • 从列表弹出项目中的迭代中收集所有剩余项目
  • 列表中加星标后的强制目标将单个项目和调整大小的列表推送到堆栈上

所以它会在第一步失败,因为你的字符串中没有强制目标。

欲了解更多信息,您可以检查unpack_iterablecaval.c

unpack_iterable(PyObject *v, int argcnt, int argcntafter, PyObject **sp)
{
    int i = 0, j = 0;
    Py_ssize_t ll = 0;
    PyObject *it;  /* iter(v) */
    PyObject *w;
    PyObject *l = NULL; /* variable list */

    assert(v != NULL);

    it = PyObject_GetIter(v);
    if (it == NULL)
        goto Error;

    for (; i < argcnt; i++) {
        w = PyIter_Next(it);
        if (w == NULL) {
            /* Iterator done, via error or exhaustion. */
            if (!PyErr_Occurred()) {
                if (argcntafter == -1) {
                    PyErr_Format(PyExc_ValueError,
                        "not enough values to unpack (expected %d, got %d)",
                        argcnt, i);
                }
                else {
                    PyErr_Format(PyExc_ValueError,
                        "not enough values to unpack "
                        "(expected at least %d, got %d)",
                        argcnt + argcntafter, i);
                }
            }
            goto Error;
        }
        *--sp = w;
    }

    if (argcntafter == -1) {
        /* We better have exhausted the iterator now. */
        w = PyIter_Next(it);
        if (w == NULL) {
            if (PyErr_Occurred())
                goto Error;
            Py_DECREF(it);
            return 1;
        }
        Py_DECREF(w);
        PyErr_Format(PyExc_ValueError,
            "too many values to unpack (expected %d)",
            argcnt);
        goto Error;
    }

    l = PySequence_List(it);
    if (l == NULL)
        goto Error;
    *--sp = l;
    i++;

    ll = PyList_GET_SIZE(l);
    if (ll < argcntafter) {
        PyErr_Format(PyExc_ValueError,
            "not enough values to unpack (expected at least %d, got %zd)",
            argcnt + argcntafter, argcnt + ll);
        goto Error;
    }

    /* Pop the "after-variable" args off the list. */
    for (j = argcntafter; j > 0; j--, i++) {
        *--sp = PyList_GET_ITEM(l, ll - j);
    }
    /* Resize the list. */
    Py_SIZE(l) = ll - argcntafter;
    Py_DECREF(it);
    return 1;

Error:
    for (; i > 0; i--, sp++)
        Py_DECREF(*sp);
    Py_XDECREF(it);
    return 0;
}

暂无
暂无

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

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