python中的切片,是一个副本或只是一个指针

时间:2014-04-12 10:22:29

标签: python list python-2.7

>>>a = [3, 2]
>>>a[0:1][0] = 1
>>>a
[3, 2]

>>>a[0:1] = [1]
>>>a
[1, 2]

a[0:1]是什么意思?

  1. 如果它是指向a范围的指针,那么a[0:1][0] = 1应该更改a的值。
  2. 如果它是a范围的副本,则a[0:1] = [1]不应更改a的值。
  3. 我认为两者的结果彼此不一致。你能帮我解决一下这个问题吗?

3 个答案:

答案 0 :(得分:6)

切片列表会创建浅层副本 - 它不是对原始文件的引用。因此,当您获得该切片时,它不会绑定到原始list a。因此,您可以尝试更改它的单个元素,但它不会存储在变量中,也不会对任何原始list进行任何更改。

澄清,前者为你做__getitem__ - 访问部分列表(副本):

a[0:1][0] = 1

您正在编辑切片[0:1],这是a的唯一浅表副本,因此不会自行编辑a

但是对于后者,一个人正在调用__setitem__,这当然会就地编辑对象。:

a[0:1] = [1]

您直接引用并编辑a的一部分,因此会实时更改。

答案 1 :(得分:6)

在内部,这是一个很大的不同:

>>>a = [3, 2]
>>>a[0:1][0] = 1

的简写
temp = a[0:1]
temp[0] = 1

并在内部表示为

a.__getitem__(slice(0, 1)).__setitem__(0, 1)

RESP。

temp = a.__getitem__(slice(0, 1))
temp.__setitem__(0, 1)

所以它访问列表的一部分,创建一个单独的对象,然后对该对象进行赋值,然后将其删除。

OTOH,

>>>a[0:1] = [1]

确实

a.__setitem__(slice(0, 1), [1])

只对原始对象进行操作。

所以,虽然看起来很相似,但这些表达方式与它们的意思截然不同。

让我们测试一下:

class Itemtest(object):
    def __init__(self, name):
        self.name = name
    def __repr__(self):
        return self.name
    def __setitem__(self, item, value):
        print "__setitem__", self, item, value
    def __getitem__(self, item):
        print "__getitem__", self, item
        return Itemtest("inner")

a = Itemtest("outer")
a[0:1] = [4]
temp = a[0:1]
temp[0] = 4
a[0:1][0] = 4

输出

__setitem__ outer slice(0, 1, None) [4]
__getitem__ outer slice(0, 1, None)
__setitem__ inner 0 4
__getitem__ outer slice(0, 1, None)
__setitem__ inner 0 4

答案 2 :(得分:0)

The following statement:

>>> a[0:1] = [1]

将列表[1]指定为从a0的列表1的子集。

通过执行a[0:1][0],您将获得[3]的第一个元素,即3.然后,如果您尝试为其指定值1,则它将无法正常工作,因为3不能为1.但是,如果您坚持a[0:1],则会收到[3]可以更改为[1]。希望有所帮助

实施例

>>> a = [1,2,3,4]
>>> a[1:4]
[2,3,4]

>>> a[1:4] = [6,5,4,3,2]
>>> a
[1,6,5,4,3,2]