如果我尝试更改重复数组中的某些值,原始数组也会受到神秘影响。
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位“官方”版本,但得到了完全相同的结果......
答案 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
绑定到x
到y
引用的对象。换句话说,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}}
请注意,两个列表都指向相同的对象。这就是为什么它被称为浅拷贝。 如果你输入一些可变对象而不是整数,就像其他列表一样,你可以清楚地理解为什么修改它会改变两个列表的内容。