简体   繁体   English

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

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

Why is为什么是

>>> a, *b = '' 

not possible, when不可能,当

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

and

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

I mean, why isn't it我的意思是,为什么不是

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

Because there is one mandatory variable specified.因为指定了一个强制变量。

The right side should have at least one item (one character for string).右侧应该至少有一项(字符串一个字符)。


According to PEP-3131 :根据PEP-3131

A tuple (or list) on the left side of a simple assignment (unpacking is not defined for augmented assignment) may contain at most one expression prepended with a single asterisk (which is henceforth called a "starred" expression, while the other expressions in the list are called "mandatory" ).简单赋值左侧的元组(或列表)(未为扩充赋值定义解包)最多可以包含一个带有单个星号的表达式(此后称为“加星号”表达式,而其他表达式在该列表称为“强制性” )。 This designates a subexpression that will be assigned a list of all items from the iterable being unpacked that are not assigned to any of the mandatory expressions, or an empty list if there are no such items.这指定了一个子表达式,该子表达式将被分配一个列表,该列表包含未分配给任何强制表达式的可迭代对象的所有项目,如果没有此类项目,则为空列表。

Based on PEP 3132 :基于PEP 3132

The function unpack_iterable() in ceval.c is changed to handle the extended unpacking, via an argcntafter parameter.功能unpack_iterable()ceval.c被改变来处理扩展拆包,经由argcntafter参数。 In the UNPACK_EX case, the function will do the following:在 UNPACK_EX 情况下,该函数将执行以下操作:

  • collect all items for mandatory targets before the starred one在加星之前收集强制性目标的所有项目
  • collect all remaining items from the iterable in a list pop items for从列表弹出项目中的迭代中收集所有剩余项目
  • mandatory targets after the starred one from the list push the single items and the resized list on the stack列表中加星标后的强制目标将单个项目和调整大小的列表推送到堆栈上

So it will failed in first step because there is no mandatory targets in your string.所以它会在第一步失败,因为你的字符串中没有强制目标。

For more info you can check unpack_iterable in caval.c :欲了解更多信息,您可以检查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