0

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

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 作为针对 Intel MKL(来自 Christoph Gohlke)与 Python 3.2.3 一起编译的 64 位版本。我还尝试了 32 位“官方”版本,但得到了完全相同的结果......

4

1 回答 1

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到 引用的对象x。换句话说,成为的引用y副本。现在被引用的对象又多了一个引用。当一个对象不再有引用时,它就会从内存中删除。Python 没有 C 中的“变量”概念。xx

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

这在每个 python 教程中都有解释,因此我建议你先搁置numpy一会,先阅读 python 教程。


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

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

现在当你做任务时:

a = 5

这是这种情况:

             ___
            (   )
            ( 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
            \___/\|
        (                                (
   )     )             (                  )   (     
  (     (      )        )        )       (  )  )     )        (
(  )  )  )    (   (    ( (    ) ( (    )  )(  (  (  (          )(
 )(  (  (   (  )   )    ) )  (   ) )  (  (  )  )  )  )      ) (  )

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

于 2013-02-05T12:37:42.523 回答