我遇到了[:]
副本中的特殊错误。
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
会相应更改。
答案 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。