bs = [1, 2, 3]
print(id(bs))
print(id(bs[:]))
xs = bs[:]
xs[1] = [9, 9, 9]
print(bs)
print(xs)
-------------
4452573000
4452573064
[1, 2, 3]
[1, [9, 9, 9], 3]
似乎bs[:]
对xs
做了深层复制
bs = [1, 2, 3]
print(id(bs))
print(id(bs[:]))
xs = bs[:] = [4, 5, 6]
print(id(xs))
print(bs)
print(xs)
----------
4518600520
4518600584
4518600584
[4, 5, 6]
[4, 5, 6]
似乎bs[:]
对xs
做了浅表复制
bs[:] = [4, 5, 6]
会将bs
的原始列表修改为[4, 5, 6]
。
但是,如果只执行xs = bs[:]
和xs[1] = [9, 9, 9]
,则不会影响仍为[1,2,3]
的bs的原始列表。
答案 0 :(得分:4)
对于列表和大多数序列类型,切片检索可对列表的切片部分进行浅表复制。在xs = bs[:]
中,xs
成为bs
bs[:] = [4, 5, 6]
中,没有复制bs
的任何部分。 [4, 5, 6]
的内容直接分配到bs
中。 (这些内容是对int对象的引用,引用是被复制的内容-我们不会对任何int进行突变。)
在链式分配xs = bs[:] = [4, 5, 6]
中,分配给xs
的值是右侧[4, 5, 6]
表达式产生的列表,而不是bs
的一部分。分配执行为
temp = [4, 5, 6]
xs = temp
bs[:] = temp
不是
bs[:] = [4, 5, 6]
xs = bs[:]
不执行切片检索,也不复制bs
。
我不知道Python语言核心,Python标准库或切片执行深度复制的任何常用第三方库中的单一类型。某些类型(例如memoryviews和NumPy数组)会返回原始对象数据的 view 以进行切片检索,但它的拷贝数比浅拷贝数少。
答案 1 :(得分:1)
从列表的一部分进行分配时,总是浅拷贝-也就是说,它会复制源列表中的引用。
当您分配给列表时(无论它是通过复制还是通过其他任何方法创建的),都不会使引用的对象发生突变-您正在更改列表中的引用,因此现在它指向其他对象。这就是您的第一个示例中的情况:
xs[1] = [9, 9, 9]
这会将xs[1]
更改为对您的新列表[9, 9, 9
的引用。 xs
内容的来源无关紧要。
这很重要,如果您有一个可变对象列表,并且对它们使用了变异方法而不是重新分配:
bs = [[1], [2], [3]]
xs = bs[:] # now xs is a shallow copy of bs - it contains references to the same objects
xs[1].append(4)
在这里,xs[1]
是对与bs[1]
相同列表的引用,因此无论您使用哪个引用来获取它,变异调用都会对其产生影响。