Numpy数组值在没有被改变的情况下发生了变化?

时间:2015-06-06 13:00:49

标签: python arrays numpy

我有两个向量, posVec dirVec 我想要保持的值(0.0,0.0,0.0)。

所以我设置了临时向量 t_pos & t_dir 并根据 cylCut

的值更改其值

然后在循环的下一次迭代中,我重置了临时向量。

代码:

import numpy as np

posVec = np.array([0.0,0.0,0.0]) # orginal vectors
dirVec = np.array([0.0,0.0,0.0])
print "................."
print 'Before'
print "................."
print posVec
print dirVec
print "................."

for cylCut in range(0,3):
    t_pos = posVec      # temporary vectors
    t_dir = dirVec
    if cylCut == 0:     # set temp vects accordingly
        print '0'
        t_pos[0] = 1.0
        t_dir[0] = 1.0
    if cylCut == 1:
        print '1'
        t_pos[1] = 1.0
        t_dir[1] = 1.0
    if cylCut == 2:
        print '2'
        t_pos[2] = 1.0
        t_dir[2] = 1.0
    print t_pos
    print t_dir

print "................."
print 'After'
print "................."
print posVec
print dirVec
print "................."

由于未知原因(至少对我而言) posVec & posDir 也正在改变。

我得到的输出,

.................
Before
.................
[ 0.  0.  0.]
[ 0.  0.  0.]
.................
0
[ 1.  0.  0.]
[ 1.  0.  0.]
1
[ 1.  1.  0.]
[ 1.  1.  0.]
2
[ 1.  1.  1.]
[ 1.  1.  1.]
.................
After
.................
[ 1.  1.  1.]
[ 1.  1.  1.]
.................

为什么会这样?我没有明确地改变向量。 Python / Numpy会自动链接变量吗?为什么要这么做?我该如何阻止它?

2 个答案:

答案 0 :(得分:5)

发生这种情况是因为

t_pos = posVec
t_dir = dirVec

复制向量的内容但复制其引用。所以基本上 t_pos posVec 指向同一个numpy数组对象。

您想要做的是:

t_pos = numpy.copy(posVec)
t_dir = numpy.copy(dirVec)

编辑:复制方法的差异:

  1 import timeit                                                                                                       
  2 import copy  
  3 import numpy as np
  4              
  5 someArr = np.arange(100)
  6              
  7 def copy1(): 
  8     tempArr = someArr.copy()
  9              
 10 def copy2(): 
 11     tempArr = np.copy(someArr)
 12              
 13 def copy3(): 
 14     tempArr = copy.copy(someArr)
 15              
 16 def copy4(): 
 17     tempArr = copy.deepcopy(someArr)
 18              
 19 print ("copy1: " + str(timeit.timeit(lambda: copy1(), number=1000000)))
 20 print ("copy2: " + str(timeit.timeit(lambda: copy2(), number=1000000)))
 21 print ("copy3: " + str(timeit.timeit(lambda: copy3(), number=1000000)))
 22 print ("copy4: " + str(timeit.timeit(lambda: copy4(), number=1000000)))

打印以下输出(以秒为单位):

copy1: 0.5677032630010217
copy2: 1.473885050001627
copy3: 1.2420436849988619
copy4: 2.733253653999782

所以是的,存在巨大的差异,但仅限于使用的计算资源。您的示例的结果保持完全相同。

someArr.copy()指的是你已经保存在内存中的对象,所以访问它是最快的方法,每个numpy数组都有这样的方法,所以基本上你是访问已经创建的numpy数组的方法。 / p>

np.copy(someArr)调用numpy库的copy-method,因此速度较慢,因为它(据我所知)在创建临时实例时产生了一些开销。

copy.copy(someArr)是一般复制对象的python(非numpy)方式。我有点困惑,它的表现略好于numpy方式...因为它的普遍性(几乎所有对象)它应该表现得更糟......至少我认为。

copy.deepcopy(someArr)显然表现最差,但记住它很重要。 Deepcopy不仅可以创建对象的副本(someArr),还可以在数组中创建新的每个元素的新副本。因此,如果您的数组中存储了对象(引用),您将面临同样的问题。因此,使用深度复制,当然不仅要创建数组的副本,而且还要创建其中每个元素的时间。

答案 1 :(得分:1)

您需要复制,您正在引用原始数组,因此其中一个数据的更改将反映在另一个数组中:

t_pos = posVec.copy()    
t_dir = dirVec.copy()

您可以使用id函数检查对象的标识:

In [2]: posVec = np.array([0.0,0.0,0.0]) # orginal vectors    
In [3]: dirVec = np.array([0.0,0.0,0.0])    
In [4]: a = posVec    
In [5]: id(a)
Out[5]: 140204693413040    
In [6]: id(posVec) # same object so same id
Out[6]: 140204693413040    
In [7]: a = posVec.copy()    
In [8]: id(posVec) 
Out[8]: 140204693413040
In [9]: id(a)
Out[9]: 140204688418096 # new object so new id

你唯一一次被抓住检查id将使用numpy数组的基本索引:

In [10]: posVec = np.array([0.0,0.0,0.0]) # orginal vectors    
In [11]: a = posVec[:2]    
In [12]: id(a)
Out[12]: 140204688417456    
In [13]: id(posVec)
Out[13]: 140204688417776    
In [14]: a[0] = 99    
In [15]: a
Out[15]: array([ 99.,   0.])  
In [16]: posVec
Out[16]: array([ 99.,   0.,   0.])

基本切片返回view 一个不拥有其数据的数组,而是引用另一个数组的数据