2016-11-05 17 views
0

就是下面的代码区别NumPy的VS自带的复制列表

内置列表代码

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

numpy的阵列

>>> c = numpy.array([1,2,3,4]) 
>>> d = c[1:3] 
>>> d[1] = 0 
>>> c 
array([1, 2, 0, 4]) 
>>> d 
array([2, 0]) 

为它在numpy arr被看见ay c直接影响。我认为在内置列表中,为变量b分配了新的内存。可能在numpy中,c [1:3]的引用被赋值为d,但我不清楚这些。 这是如何工作的numpy和内置?

+0

的可能的复制[阵VS矢量VS列表(http://stackoverflow.com/questions/1905417/array-vs -vector-vs-list) – polka

+0

@波尔卡感谢您的快速回答,但对我来说还不够清楚。 – umtkas

+0

请注意,谈论一个numpy列表是不正确的。它是一个数组。 – chthonicdaemon

回答

2

要理解的关键是Python中的每个赋值都将名称与内存中的对象关联起来。 Python从不复制任务。现在变得重要的是要了解何时创建新对象以及它们如何表现。

在第一个示例中,列表中的切片会创建一个新的列表对象。在这种情况下,两个列表都会引用一些相同的对象(int 2和int 3)。这些引用被复制的事实就是所谓的“浅”副本。换句话说,引用被复制,但它们引用的对象仍然是相同的。请记住,无论存储在列表中的事物的类型如何,情况都是如此。

现在,我们创建一个新对象(int 0)并指定b[1] = 0。由于ab是单独的列表,因此它们现在显示不同的元素并不让我们感到惊讶。

我喜欢pythontutor visualisation这种情况。

在数组情况下,"All arrays generated by basic slicing are always views of the original array."

这个新对象与原始数据共享数据,索引分配的处理方式是视图的任何更新都会更新共享数据。

2

这已被涵盖很多,但找到一个很好的重复是太多的工作。 :(

让我们来看看,如果我能很快描述的东西与你的例子:

>>> a = [1,2,3,4] # a list contains pointers to numbers elsewhere 
>>> b = a[1:3] # a new list, with copies of those pointers 
>>> b[1] = 0 # change one pointer in b 
>>> a 
[1, 2, 3, 4] # does not change any pointers in a 
>>> b 
[2, 0] 

array具有不同的结构 - 它与“原始”号(或其他字节值)数据缓冲区

numpy array 
>>> c = numpy.array([1,2,3,4]) 
>>> d = c[1:3]  # a view; a new array but uses same data buffer 
>>> d[1] = 0  # change a value in d; 
>>> c 
array([1, 2, 0, 4]) # we see the change in the corrsponding slot of c 
>>> d 
array([2, 0]) 

与列表中的关键点是,它们包含对象的指针可以复制三分球不复制的对象;并且可以更改指针不改变指针的其他副本

为了节省内存并加快numpy的执行概念view。它可以在不复制原始数据的情况下创建一个新数组 - 因为它可以共享数据缓冲区。但是也可以复制,例如

e = c[1:3].copy() 
e[0] = 10 
# no change in c 

view v copynumpy一个很大的话题和根本性的,不同种类的索引(切片,基本,高级)时尤其如此。我们可以提供帮助,但您也应该阅读numpy文档。理解存储numpy阵列的基础知识是无可替代的。

http://scipy-cookbook.readthedocs.io/items/ViewsVsCopies.html

http://www.scipy-lectures.org/advanced/advanced_numpy/(可能是更高级的那是你现在需要)