【问题标题】:How is p[a:b:c] handled by python?python如何处理p[a:b:c]?
【发布时间】:2019-06-27 00:58:49
【问题描述】:

我在 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 列表的更改反映在原始列表中!

【问题讨论】:

  • 在 Qn2 中,我不是在询问符号。但是关于(子)列表是如何创建和管理的,它究竟包含什么?它是对原始列表中项目的引用列表吗?

标签: python python-3.x slice


【解决方案1】:

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

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

【讨论】:

  • 对于我提到的“罕见异常”,想想memoryview 内置数组和numpy 数组,它们不执行浅拷贝,而是创建底层内存的新视图。 id 在那里更没用,因为它会告诉你子切片有不同的身份,但在这些情况下,它实际上共享底层存储。
【解决方案2】:

对于问题 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 基于y 创建一个新列表x,得到 相关元素。

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

【讨论】:

  • 优秀的答案,非常详细!但是我将另一个答案标记为答案,因为它基本上传达了与这个答案相同的方面(尽管细节较少)但排在第一位。
猜你喜欢
  • 1970-01-01
  • 2012-08-30
  • 1970-01-01
  • 2015-03-24
  • 2021-03-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-09-21
相关资源
最近更新 更多