【问题标题】:Numpy array values changed without being aksed?Numpy 数组值更改而不被询问?
【发布时间】:2015-06-06 13:00:49
【问题描述】:

我有 2 个向量,posVecdirVec,我希望将它们的值保持在 (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 "................."

出于未知原因(至少对我而言),posVecposDir 的内容也正在更改。

我得到的输出,

.................
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 会自动链接变量吗?为什么要这么做?我该如何阻止它?

【问题讨论】:

标签: python arrays numpy


【解决方案1】:

这是因为

t_pos = posVec
t_dir = dirVec

不是复制向量的内容,而是复制它们的引用。所以基本上 t_posposVec 都指向同一个 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 数组的方法。

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

copy.copy(someArr) 是python(非numpy)复制对象的一般方式。我有点困惑,它的性能比 numpy 方式略好...因为它的通用性(几乎所有对象)它应该表现更差...至少我是这么认为的。

copy.deepcopy(someArr) 显然表现最差,但记住这一点很重要。 Deepcopy 不仅会创建对象的副本 (someArr),还会创建数组中 每个 元素的新副本。因此,如果您的数组中存储了对象(引用),您将面临同样的问题。因此使用了 deepcopy,当然不仅要创建数组的副本,还要创建其中的每个元素的副本。

【讨论】:

  • 谢谢 我不知道。 numpy.copy(posVec) 和 posVec.copy() 有什么区别吗?
  • 开销是函数调用没有创建任何实例
【解决方案2】:

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

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,它是不拥有其数据的数组,而是引用另一个数组的数据

【讨论】:

    猜你喜欢
    • 2020-08-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-06-14
    • 1970-01-01
    • 2018-07-07
    • 2017-03-04
    相关资源
    最近更新 更多