索引重复的NumPy数组也会影响原始数组

时间:2013-02-05 12:35:49

标签: numpy

如果我尝试更改重复数组中的某些值,原始数组也会受到神秘影响。

import numpy as np

x = np.zeros((3, 10))
y = x

print(x)
print(y, "\n")

y[1:3, 4:8] = 1

print(x)
print(y)

我系统的输出如下:

[[ 0.  0.  0.  0.  0.  0.  0.  0.  0.  0.]
 [ 0.  0.  0.  0.  0.  0.  0.  0.  0.  0.]
 [ 0.  0.  0.  0.  0.  0.  0.  0.  0.  0.]]
[[ 0.  0.  0.  0.  0.  0.  0.  0.  0.  0.]
 [ 0.  0.  0.  0.  0.  0.  0.  0.  0.  0.]
 [ 0.  0.  0.  0.  0.  0.  0.  0.  0.  0.]]

[[ 0.  0.  0.  0.  0.  0.  0.  0.  0.  0.]
 [ 0.  0.  0.  0.  1.  1.  1.  1.  0.  0.]
 [ 0.  0.  0.  0.  1.  1.  1.  1.  0.  0.]]
[[ 0.  0.  0.  0.  0.  0.  0.  0.  0.  0.]
 [ 0.  0.  0.  0.  1.  1.  1.  1.  0.  0.]
 [ 0.  0.  0.  0.  1.  1.  1.  1.  0.  0.]]

我目前正在使用NumPy 1.6.2作为针对英特尔MKL(来自Christoph Gohlke)和Python 3.2.3编译的64位版本。 我也尝试了32位“官方”版本,但得到了完全相同的结果......

1 个答案:

答案 0 :(得分:1)

你做了创建数组的副本。您只需在同一个数组中创建一个新的引用。如果要复制数组,请使用numpy.copy

y = numpy.copy(x)

请注意,使用常规python列表,您可以获得语法为the_list[:]的浅表副本(其中[:]表示创建一个从原始列表的开头开始到结尾的切片),在大多数情况下,numpy切片实际上是视图

>>> import numpy as np
a>>> a = np.arange(10)
>>> b = a[:]
>>> b[0] = 100
>>> a
array([100, 1, 2, 3, 4, 5, 6, 7, 8, 9])
>>> b
array([100, 1, 2, 3, 4, 5, 6, 7, 8, 9])

对战:

>>> a = range(10)
>>> b = a[:]    # does a real copy
>>> b[0] = 100
>>> a
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> b
[100, 1, 2, 3, 4, 5, 6, 7, 8, 9]

在python中,每个标识符都是对象的引用。当你完成任务时:

y = x

赋值将名称y绑定到xy引用的对象。换句话说,x会成为x的参考的副本。现在y = x引用的反对意见还有一个参考。当一个对象不再有引用时,它将从内存中删除。 Python没有像C中所见的“变量”概念。

另一种思维方式是任何标识符都是指向对象的指针。因此PyObject复制指针而不是对象本身(这就是实际发生的事情.C / API总是使用指向numpy结构的指针)

每个python教程都会对此进行解释,因此我建议您暂时放下a = 5 并先阅读python教程。


我决定用一些Unicode艺术来说明绑定会发生什么。 这个想法不是我的,而是来自python-it.org forum的用户Claudio_F。

我的想法是在python中你有标识符,我将其表示为浮标。每个浮标可以连接到一个物体,该物体在海底下被表示为岩石(或其他)。 物体可以绑定到更多的浮标。当一个物体没有被任何浮标束缚时,它会沉入海中,当它到达海底时,一个巨大的海怪会摧毁它(比如垃圾收集器)。

现在当你完成任务时:

             ___
            (   )
            ( a )
            (   )
^~~~~^~~~~^~~'¿'~~~~^~~~~~^~~~~~^~~~~~~
              |
  O        .--+--.         o    ___
           |  5  |           |\/  x\
           .-----.            ^\_/


             ___             O
    o       /o  \/|
            〉 GC  |       o      o
            \___/\|
        (   
   )     )             (
  (     (      )        )        )
(  )  )  )    (   (    ( (    ) ( (
 )(  (  (   (  )   )    ) )  (   ) )

情况就是这样:

b = a

执行作业时:

            ___               ___
           (   )             (   )
           ( a )             ( b )
           (   )             (   )
^~~~^~~~~^~~'¿'~~~~~^~~~~^~~~~'¿'~~~~^~~~~~^
             \        o       /
              \     o        /
               \     O      /
                \          /    __________
                 \        /    /          \
       o          \      /    /            \
                   \    /       )  | (  | )
     O              \  /       (   |  )  (
        o            \/            | (    )
                  .--+--.             )
                  |  5  |
                  .-----.



             ___             O
    o       /o  \/|
            〉 GC  |       o      o
            \___/\|
        (   
   )     )             (
  (     (      )        )        )
(  )  )  )    (   (    ( (    ) ( (
 )(  (  (   (  )   )    ) )  (   ) )

两个浮标都绑定在同一个物体上:

a = 7

当您完成第三项任务时:

a

5链从7对象解开并绑定到新的b对象,但5的浮标仍然绑定到 ___ ___ ( ) ( ) ( a ) ( b ) ( ) ( ) ^~~~^~~~~^~~'¿'~~~~~^~~~~^~~~~'¿'~~~~^~~~~~^ | o | | | | O | o | | o | | | o | | .--+--. O .--+--. | 5 | | 7 | .-----. .-----. o ___ O o /o \/| 〉 GC | o o \___/\| ( ) ) ( ( ( ) ) ) ( ) ) ) ( ( ( ( ) ( ( )( ( ( ( ) ) ) ) ( ) )

L = [1,2,3]

我希望你喜欢这些照片,并且明确了它们是如何运作的。 (水母和死鱼都在那里,因为我认为它们很酷)

顺便说一句,这种表示对于理解对象之间的引用也很棒。 例如代码:

                ___
               (   )
               ( L )
               (   )
 ^~~~~^~~~~^~~~~'¿'~~~~^~~~~^~~~~^~~~~^
                 |
                 |
        .--------+----------.
        | [ '¿', '¿', '¿' ] |
        .----|----|----|----.
            /     |     \
           /      |      \
       .--+--.    |    .--+--.
       |  1  |    |    |  3  |
       .-----.    |    .-----.
                  |
               .--+--.
               |  2  |
               .-----.



             ___             O
    o       /o  \/|
            〉 GC  |       o      o
            \___/\|
        (   
   )     )             (
  (     (      )        )        )
(  )  )  )    (   (    ( (    ) ( (
 )(  (  (   (  )   )    ) )  (   ) )

将表示如下:

R = L[:]

注意列表如何包含对象的“指针”,而不是实际的对象。

此外,如果您这样做,请回到切片:

                ___                        ___
               (   )                      (   )
               ( L )                      ( R )
               (   )                      (   )
 ^~~~~^~~~~^~~~~'¿'~~~~^~~~~^~~~~^~~~~^~~~~'¿'~~~~~~^~~~~~^~~~~~
                 |                          |
                 |                          |
        .--------+----------.     .---------+---------.
        | [ '¿', '¿', '¿' ] |     | [ '¿', '¿', '¿' ] |
        .----|----|----|----.     .----|----|----|----.
             \     \    \             /    /    /
              \     \    \           /    /    /
               \     \    \         /    /    /
                \     \    \       /    /    /
                 \     \    \     /    /    /
                  \     \    \   /    /    /
                   \     \    \ /    /    /
                    \     | .--+--. |    /
                     \    | |  1  | |   /
                      \   | .-----. |  /
                       \   \       /  /
                        \   \     /  /
                         \   \   /  /
                          |   \ /   |
                          | .--+--. |
                          | |  2  | |
                          | .-----. |
                           \       /
                            \     /
                             \   /
                              \ /
                            .--+--.
                            |  3  |
                            .-----.



             ___             O
    o       /o  \/|
            〉 GC  |       o      o
            \___/\|
        (                                (
   )     )             (                  )   (     
  (     (      )        )        )       (  )  )     )        (
(  )  )  )    (   (    ( (    ) ( (    )  )(  (  (  (          )(
 )(  (  (   (  )   )    ) )  (   ) )  (  (  )  )  )  )      ) (  )

您获得此方案:

{{1}}

请注意,两个列表都指向相同的对象。这就是为什么它被称为浅拷贝。 如果你输入一些可变对象而不是整数,就像其他列表一样,你可以清楚地理解为什么修改它会改变两个列表的内容。