【发布时间】:2016-04-11 23:35:17
【问题描述】:
我知道 w 语法是如何工作的,但我想知道 python 如何替换和更改左侧列表的过程。 例如。
L = [0, 1, 2, 3, 4]
L[0:2] = [5]
print L #L is now [5, 2, 3, 4]
python 是怎么做的?
【问题讨论】:
标签: python list python-2.7
我知道 w 语法是如何工作的,但我想知道 python 如何替换和更改左侧列表的过程。 例如。
L = [0, 1, 2, 3, 4]
L[0:2] = [5]
print L #L is now [5, 2, 3, 4]
python 是怎么做的?
【问题讨论】:
标签: python list python-2.7
这是通过__setitem__ 或__setslice__ 方法完成的。 (__setslice__ 已弃用 IIRC 并在 python3.x 中删除)。
对于列表,表达式:
L[start: stop] = some_iterable
将从some_iterable 获取项目并替换索引处的元素从开始到停止(不包括在内)。因此,在您的演示代码中,您有:
L[0:2] = [5]
这将获取索引0 和1 处的元素并将它们替换为5。
请注意,替换列表的长度不必与要替换的子列表长度相同。
也许更好的方式是将其视为执行以下操作的就地方式:
L[a:b] = c
# equivalent to the following operation (done in place)
L[:a] + list(c) + L[b:]
如果您真的对它如何感到好奇,源代码是最好的参考。 PyList_SetSlice 调用 list_ass_slice 将右侧的可迭代对象转换为序列(tuple 或 list IIRC)。它调整数组的大小以保存适当数量的数据,将切片右侧的内容复制到适当的位置,然后复制新数据。根据列表是增长还是缩小,有几种不同的代码路径(和操作顺序),但这是它的基本要点。
【讨论】:
在您的问题被标记的python 2.7 中,它是__setslice__ 魔术方法。详细信息记录在here in the datamodel section。
__setslice__(self, i, j, sequence)
Called to implement assignment to self[i:j].
这是一个用于向后兼容的旧接口。例如,如果您使用L[0:2:](应该是等效的)分配给一个切片,您实际上是通过__setitem__ 的新接口。
要了解幕后发生的事情,您可以创建自己的类并继承一个列表:
>>> class MyList(list):
... def __setslice__(self, *args):
... print '__setslice__ called with args:', args
... list.__setslice__(self, *args)
... def __setitem__(self, *args):
... print '__setitem__ called with args:', args
... list.__setitem__(self, *args)
...
我们来看几个例子:
>>> L = MyList([0, 1, 2, 3, 4])
>>> L[0:2] = [5]
__setslice__ called with args: (0, 2, [5])
传递的 3 个参数始终是左右端点,然后是赋值右侧的对象。
>>> L[0:2:] = [5]
__setitem__ called with args: (slice(0, 2, None), [5])
使用带有步骤的切片将始终通过__setitem__ 的新接口,并传递slice 对象的实例而不是开始/停止索引。
>>> L[1:] = [5]
__setslice__ called with args: (1, 9223372036854775807, [5])
省略端点使用sys.maxint(省略开始使用0)。
>>> L[::] = 'potato'
__setitem__ called with args: (slice(None, None, None), 'potato')
右边的对象不一定是列表。
我要提到的最后一件事是,如果您是从内置列表类型派生的,那么您只需要使用__setslice__。通常您不想要这样做,如果您正在编写新代码,现代方式将是继承abstract base class,特别是collections.Sequence 是类列表结构的明显选择。这样,您就不必担心内置列表具有向后兼容性的所有缺陷和技巧。
【讨论】: