Python-数组复制/分配,意外'=数组[:]和#x27;努比的行为
我正在阅读有关按引用或值复制数组(&list)的内容。然而,我在这里遇到了一个问题。。为了说明我的问题,我举了三个例子,每个例子都有一个作业和一个变化 第一个示例:默认情况下,它是通过引用复制的。Python-数组复制/分配,意外'=数组[:]和#x27;努比的行为,python,arrays,list,pass-by-reference,pass-by-value,Python,Arrays,List,Pass By Reference,Pass By Value,我正在阅读有关按引用或值复制数组(&list)的内容。然而,我在这里遇到了一个问题。。为了说明我的问题,我举了三个例子,每个例子都有一个作业和一个变化 第一个示例:默认情况下,它是通过引用复制的。 因此,更改将影响a和ArrayA,它们都具有相同的地址。嗯 第二个示例:由于首先计算右侧,*1不会更改其值,但会导致按值复制。(我认为这也可以通过其他几种方式实现,比如使用copy()和..)。 因此,更改只影响c,其地址与ArrayC不同。嗯 第三个例子: 在这里,我将[:]添加到数组中,从而复制数
因此,更改将影响a和ArrayA,它们都具有相同的地址。嗯 第二个示例:由于首先计算右侧,*1不会更改其值,但会导致按值复制。(我认为这也可以通过其他几种方式实现,比如使用copy()和..)。
因此,更改只影响c,其地址与ArrayC不同。嗯 第三个例子: 在这里,我将[:]添加到数组中,从而复制数组(=按值),据我所知。可以通过e和ArrayE的不同地址确认。然而,这种变化不仅影响e,还影响ArrayE。对我来说,这是非常出乎意料的,因为它甚至显示了我以前的不同地址。为什么? 谢谢你了()
将numpy导入为np
#示例1,通过引用
ArrayA=np.数组([5,2,3,5,4])
ArrayB=np.array([1,2,3,4])
a=ArrayA
a[1::]+=ArrayB
打印(“{}:\t{},\tid:{}”。格式(“ArrayA”,ArrayA,id(ArrayA)))
打印(“{}:\t{},\tid:{}”。格式(“ArrayB”,ArrayB,id(ArrayB)))
打印(“{}:\t{},\tid:{}”。格式(“a”,a,id(a)))
ArrayC=np.数组([5,2,3,5,4])
ArrayD=np.数组([1,2,3,4])
#示例2,按值
c=ArrayC*1
c[1::]+=ArrayD
打印()
打印(“{}:\t{},\tid:{}”。格式(“ArrayC”,ArrayC,id(ArrayC)))
打印(“{}:\t{},\tid:{}”。格式(“ArrayD”,ArrayD,id(ArrayD)))
打印(“{}:\t{},\tid:{}”。格式(“c”,c,id(c)))
#示例3,通过引用/值?!?!
ArrayE=np.数组([5,2,3,5,4])
ArrayF=np.数组([1,2,3,4])
e=ArrayE[:]
e[1::]+=ArrayF
打印()
打印(“{}:\t{},\tid:{}”。格式(“ArrayE”,ArrayE,id(ArrayE)))
打印(“{}:\t{},\tid:{}”。格式(“ArrayF”,ArrayF,id(ArrayF)))
打印(“{}:\t{},\tid:{}”。格式(“e”,e,id(e)))
ArrayA:[53588],id:2450575020480
ArrayB:[1234],id:2450575021680
答:[53588],身份证号码:2450575020480
ArrayC:[52354],id:2450575021280
阿拉伊德:[1234],身份证号码:2450575022080
c:[53588],识别号:2450575022240
阿拉耶:[53588],身份证号码:2450575022640
阵列:[1234],id:2450575022000
e:[53588],识别号:2450575022880
编辑-请参见下面的@juanpa.arrivillaga评论
在所有示例中,ndarrays
的值都是numpy.int32
对象,它们是可变的因此,从第三个示例来看,
e
和ArrayE
都指向相同的numpy.int32
对象。这就是为什么这些变化会反映在这两个方面。
您可以通过检查他们的ID来验证这一点
print(id(e[0])==id(ArrayE[0]))
编辑-请参见下面的@juanpa.arrivillaga评论
在所有示例中,ndarrays
的值都是numpy.int32
对象,它们是可变的因此,从第三个示例来看,
e
和ArrayE
都指向相同的numpy.int32
对象。这就是为什么这些变化会反映在这两个方面。
您可以通过检查他们的ID来验证这一点
print(id(e[0])==id(ArrayE[0]))
“参照复制”不是一件事。你应该先阅读,然后重新组织你的问题。这不是“引用副本”,根本不是副本。注意,这与按引用传递和按值传递无关,它们是评估策略,即如何/何时评估函数参数的语义。注意,Python既不使用按值调用,也不使用按引用调用。当您切片numpy.ndarray
对象时,它会创建一个新的数组对象,该对象是切片数组中底层缓冲区的视图。“按引用复制”不是一件事。你应该先阅读,然后重新组织你的问题。这不是“引用副本”,根本不是副本。注意,这与按引用传递和按值传递无关,它们是评估策略,即如何/何时评估函数参数的语义。注意,Python既不使用按值调用,也不使用按引用调用。当您切片numpy.ndarray
对象时,它会创建一个新的数组对象,该对象是被切片数组中底层缓冲区的视图。因此,我的观点是正确的:因此使用[:]会生成一个不同的数组,正如我所做的id(e)
的不同地址所示。但是新数组的字段保持不变,因为匹配的id(e[0])
显示?@wuuuuuuu2正确。如果使用常规python列表而不是numpy数组,则值将是int类型的,这是不可变的。因此,一个列表上的更改不会修改另一个列表。不,数组中的值及其可变性是无关的。在python中切片列表将使用浅层复制语义创建一个新的列表对象。numpy.ndarray
的一个切片创建了一个新的数组对象,该对象是底层原语缓冲区的视图。另外,请注意,数组实际上不包含numpy.int32
对象numpy.ndarray
具有数字/结构化数据类型的对象本质上是原始类C数组上的面向对象包装器numpy.int32
和各种数据类型实际上仅在访问数组中的值以进入解释器级别时临时存在,有点像Java中的自动装箱。@juanpa.arrivillaga更有意义。谢谢所以我的观点是正确的:所以使用[:]会产生一个不同的数组,正如我使用的不同地址所看到的那样id(e)
。但是新数组的字段保持不变,因为匹配的id(e[0])
显示?@wuuuuuuu2正确。如果使用常规python列表而不是numpy数组,则值将是int类型的,这是不可变的。因此,一个列表上的更改不会修改另一个列表。不,数组中的值及其可变性是ir