为什么`mylist [:] = reverse(mylist)`工作?

Ste*_*ann 11 python reverse list python-internals assign

以下反转列表"就地"并在Python 2和3中工作:

>>> mylist = [1, 2, 3, 4, 5]
>>> mylist[:] = reversed(mylist)
>>> mylist
[5, 4, 3, 2, 1]
Run Code Online (Sandbox Code Playgroud)

为什么/怎么样?既然reversed给了我一个迭代器,并且不预先复制列表,并且因为[:]=替换"就地",我很惊讶.以下,也使用reversed,按预期中断:

>>> mylist = [1, 2, 3, 4, 5]
>>> for i, item in enumerate(reversed(mylist)):
        mylist[i] = item
>>> mylist
[5, 4, 3, 4, 5]
Run Code Online (Sandbox Code Playgroud)

为什么不是这样的[:] =失败?

是的,我知道mylist.reverse().

Ash*_*ary 12

CPython list slice assigment将首先通过调用将iterable转换为列表PySequence_Fast.资料来源:https://hg.python.org/cpython/file/7556df35b913/Objects/listobject.c#l611

 v_as_SF = PySequence_Fast(v, "can only assign an iterable");
Run Code Online (Sandbox Code Playgroud)

甚至PyPy也做了类似的事情:

def setslice__List_ANY_ANY_ANY(space, w_list, w_start, w_stop, w_iterable):
    length = w_list.length()
    start, stop = normalize_simple_slice(space, length, w_start, w_stop)
    sequence_w = space.listview(w_iterable)
    w_other = W_ListObject(space, sequence_w)
    w_list.setslice(start, 1, stop-start, w_other)
Run Code Online (Sandbox Code Playgroud)

这里space.listview将调用ObjSpace.unpackiterable解包迭代,然后返回一个列表.

  • 我已经害怕它三次大喊"任意"了. (3认同)