[:]切片只能制作列表的浅表副本吗?

时间:2014-12-23 23:55:33

标签: python numpy

我遇到了[:]副本中的特殊错误。

The docs[:]只做一个浅拷贝,但似乎是:

a = [1,2,3]
id(a)
3071203276L
b=a[:]
id(b)
3071234156L

id(a)不等于id(b);怎么只是一个浅的副本?

特殊情况:

import numpy as np
import random
a = np.array([1,2,3])
b=a[:]
random.shuffle(a)

b会相应更改。

5 个答案:

答案 0 :(得分:5)

Numpy回答:

numpy中的数组是后备存储上的视图/索引

您可以复制视图,而无需复制后备存储...

a=numpy.array([1,2,3,4])
b=a[:] # copy of the array ("view" or "index"), not the storage
b.shape=(2,2)
print a
# [1 2 3 4]
print b
# [[1 2]
#  [3 4]]
b *= 2
print a
# [2 4 6 8]
print b
# [[2 4]
#  [6 8]]

了解更改b如何影响?然而他们仍然有不同的形状。将它们视为数据视图;并且b=a[:]行只复制了此视图。我甚至可以修改b的形状。因为它只是数据的索引,所以表示列和行位于内存中。

如果您想要numpy中的后备存储副本,请使用a.copy()

答案 1 :(得分:4)

这是一个浅层副本,但在这种情况下更改b不会影响a,因为元素只是数字。如果它们是引用,那么a将被更新:

a = [1, 2, 3]
b = a[:]

b[1] = 5
print "a: ", a
print "b: ", b
# a: [1, 2, 3]
# b: [1, 5, 3]

VS

a = [[1], [2], [3]]
b = a[:]

b[1][0] = 5
print "a: ", a
print "b: ", b
# a:  [[1], [5], [3]]
# b:  [[1], [5], [3]]

答案 2 :(得分:0)

不同之处在于列表a和列表b的元素是相同的。更改任一列表中的可变对象也会影响其他列表中的元素。

相比之下,深度复制尝试创建一组完全不同的对象。

答案 3 :(得分:0)

可能唯一能制作深层副本的是deepcopy

因为深拷贝很昂贵,因为您需要跟踪复制的每个对象。

考虑这样的邪恶结构:

a = []
a.append(a)

你当然不想做一个天真的深刻的副本。

所以是的,这是一个浅薄的副本。但在您的示例中,它是存储基元,它将作为值复制,而不是作为引用复制。因此,修改一个列表不会修改另一个列表。

id()不能用于区分浅拷贝和深拷贝

它区分副本和非副本(具有相同的ID)。

a = [1, 2, 3]
b = a
print id(b), id(a), "no surprise, same id, no copy."

Numpy数组不同

在这里,你只是"浅拷贝"索引,而不是后备存储中的数据。如果您想确保拥有副本,请使用.copy()

答案 4 :(得分:0)

Numpy定义了slice与标准python库的不同之处。这是因为numpy可以处理大量数据。并不总是需要复制这些巨大的数组,特别是如果用户只想要一个临时的数组视图。例如,arr[:100].sum()对前100个元素求和,而不必创建前100个元素的临时浅拷贝。请注意,仅为基本切片创建临时视图。

有关详细信息,请参阅documentation