python如何处理p [a:b:c]?

时间:2019-06-27 00:58:49

标签: python python-3.x slice

我正在python shell中尝试这些,并且得到了相当混乱的结果。

>>> p = [1, 2, 3, 4, 5, 6, 7, 8] 
>>> p 
[1, 2, 3, 4, 5, 6, 7, 8]
>>> p[2:8:2]
[3, 5, 7]
>>> id(p[2:8:2])
37798416
>>> id(p[2:8:2])
37798416
>>> id(p[2:8:2])
50868392

请注意ID是如何第三次更改的!

>>> id(p[2:8:2])
37798336

再次更改! 问题1:这是怎么发生的以及为什么发生的?

问题2:

>>> p[2:8:2] = [33,55,77]
>>> p
[1, 2, 33, 4, 55, 6, 77, 8]

python如何精确“存储” p [2:8:2]? (可能“存储”不是正确的词,但希望您能理解)。它看起来好像不是与原始列表不同的列表(尽管它由原始列表中的非顺序不可变项组成),因为对 this 列表的更改反映在原始列表中!

2 个答案:

答案 0 :(得分:4)

切片(很少有例外)会为要切片的内容制作全新的副本。因此,所有PySliceObject检查都告诉您,有时新的x重用上一次的内存,有时又使用不同的内存。确切的行为是纯实现细节。在CPython(参考解释器)中,id恰好对应于内存地址,因此您所看到的只是分配器的行为工件,而不是切片的深层含义。

关于问题2:在分配上下文中使用时,切片会修改原始序列,根本不会创建新的list。不要试图在切片(面向读取,创建新序列)和切片分配(面向写入,修改现有序列)之间绘制有意义的相似之处;引擎盖下的行为几乎在各个方面都不同。

答案 1 :(得分:1)

问题1:

保证对象的ID既唯一,又在该对象的生存期内保持不变。请参见here in the Python library docs

  

id(object)-返回对象的身份。这是一个整数,可以保证在此对象的生存期内唯一且恒定。具有不重叠生存期的两个对象可能具有相同的id()值。

由于您正在使用切片创建和销毁对象,因此id实际上遵循规则。

如果您使用的是CPython的引用(并且我怀疑是最常见的)实现,则它只是为您提供对象的内存地址。可以在Python/bltinmodule.c中找到源代码,下面对其进行了简化和注释:

static PyObject *builtin_id(PyModuleDef *self, PyObject *v) {
    PyObject *id = PyLong_FromVoidPtr(v); // Turn object address into
    return id;                            //    long and return it.
}

这确保了它的唯一性,并且内存分配调用的变化和顺序也解释了为什么它可以重复和/或不同。


问题2:

分配给“切片”实际上不是涉及创建切片对象并对其进行分配。只需将切片符号指定的现有值中的某些值设置为赋值右侧的值即可。

更多细节可以在CPython源代码的sliceobject文件中找到,尤其是Objects/sliceobject.cInclude/sliceobject.h。这些操作涉及创建一个PySliceObject元组的{start, stop, step}

当将此元组应用于分配右侧的对象时,例如x = y[2:8:2],它会使用PySliceObject根据{{ 1}},仅获取 相关元素。

侧使用时,例如x,它使用y来决定x[2:8:2] = [33,55,77]的哪些元素被设置为正确的。