提问人:Wuhuuu2 提问时间:4/28/2020 最后编辑:Wuhuuu2 更新时间:4/29/2020 访问量:89
Python - 数组复制/分配,numpy 的意外“=array[:]”行为
Python - array copying/assign, unexpected '=array[:]' behaviour for numpy
问:
我正在阅读有关通过引用或值复制数组 (&list) 的信息。但是,我在这里遇到了一个问题。为了说明我的问题,我举了三个例子,每个例子都有一个作业和一个更改。
第一个示例:默认情况下,它通过引用进行复制。
因此,该更改会产生 a 和 ArrayA,两者都具有相同的地址。还行
第二个示例:由于首先计算右侧,因此 *1 不会更改其值,但会导致按值复制。(我认为这也可以通过其他几种方式完成,例如使用 copy() 和 ..)
因此,更改仅影响 c,其地址与 ArrayC 不同。还行
第三个示例:据我了解,这里我将 [:] 添加到数组中,从而复制数组(=按值)。可以通过 e 和 ArrayE 的不同地址来确认。但是,此更改不仅影响 e,还影响 ArrayE。对我来说,这几乎是出乎意料的,因为它甚至向我展示了不同的地址。为什么?
提前致谢=)
import numpy as np
# Example 1, by reference
ArrayA = np.array([5,2,3,5,4])
ArrayB = np.array( [1,2,3,4])
a = ArrayA
a[1:] += ArrayB
print("{}:\t{},\tid: {}".format("ArrayA",ArrayA, id(ArrayA) ))
print("{}:\t {},\tid: {}".format("ArrayB",ArrayB, id(ArrayB) ))
print("{}:\t{},\tid: {}".format("a",a, id(a) ))
ArrayC = np.array([5,2,3,5,4])
ArrayD = np.array( [1,2,3,4])
# Example 2, by value
c = ArrayC*1
c[1:] += ArrayD
print()
print("{}:\t{},\tid: {}".format("ArrayC",ArrayC, id(ArrayC) ))
print("{}:\t {},\tid: {}".format("ArrayD",ArrayD, id(ArrayD) ))
print("{}:\t{},\tid: {}".format("c",c, id(c) ))
# Example 3, by reference/value?!?!
ArrayE = np.array([5,2,3,5,4])
ArrayF = np.array( [1,2,3,4])
e = ArrayE[:]
e[1:] += ArrayF
print()
print("{}:\t{},\tid: {}".format("ArrayE",ArrayE, id(ArrayE) ))
print("{}:\t {},\tid: {}".format("ArrayF",ArrayF, id(ArrayF) ))
print("{}:\t{},\tid: {}".format("e",e, id(e) ))
ArrayA: [5 3 5 8 8], id: 2450575020480
ArrayB: [1 2 3 4], id: 2450575021680
a: [5 3 5 8 8], id: 2450575020480
ArrayC: [5 2 3 5 4], id: 2450575021280
ArrayD: [1 2 3 4], id: 2450575022080
c: [5 3 5 8 8], id: 2450575022240
ArrayE: [5 3 5 8 8], id: 2450575022640
ArrayF: [1 2 3 4], id: 2450575022000
e: [5 3 5 8 8], id: 2450575022880
答:
0赞
ywbaek
4/28/2020
#1
已编辑 - 请参阅下面的 @juanpa.arrivillaga 的评论。
在所有示例中,的值是
可变的对象。
因此,从第三个示例中,两者都指向相同的对象。
这就是为什么这些变化都反映在两者上的原因。
您可以通过检查他们的 ID 来验证这一点。ndarrays
numpy.int32
e
ArrayE
numpy.int32
print(id(e[0]) == id(ArrayE[0]))
评论
0赞
Wuhuuu2
4/29/2020
所以我是对的:所以使用 [:] 会产生一个不同的数组,就像我这样做的方式一样。但是新数组的字段保持不变,如您的匹配所示?id(e)
id(e[0]))
0赞
ywbaek
4/29/2020
@Wuhuu2正确。如果使用常规的 python 列表而不是 numpy 数组,则值将是 int 类型,这是不可变的。因此,一个列表上的更改不会修改另一个列表。
0赞
juanpa.arrivillaga
4/29/2020
否,数组中的值及其可变性无关紧要。在 python 中对列表进行切片会使用浅拷贝语义创建一个新的列表对象。a 的切片创建一个新的数组对象,该对象是基础基元缓冲区的视图。numpy.ndarray
0赞
juanpa.arrivillaga
4/29/2020
另请注意,数组实际上不包含对象。 具有数字/结构化 dtypes 的对象本质上是原始类 C 数组上的面向对象的包装器。 而各种 dtypes 实际上只在你访问数组中的值时才短暂存在,以便将其引入解释器级别,有点像 Java 中的自动装箱。numpy.int32
numpy.ndarray
numpy.int32
0赞
ywbaek
4/29/2020
@juanpa.arrivillaga 这更有意义。谢谢!
上一个:递归下实例变量和实例对象的行为
评论
numpy.ndarray