numpy 深拷贝、浅拷贝和视图总结和例子
ndarray类的索引和切片方法
组切片得到的是原始数组的视图,所有修改都会直接反映到源数组。如果需要得到的ndarray 切片的一份副本,需要进行复制操作
比如
arange[5:8].copy()
Python的列表序列不同,通过下标范围获取的新的数组是原始数组的一个视图。它与原始数组共享同一块数据空间.
import numpy as np
a=np.arange(10)
a
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
b=a[3:7]
b
array([3, 4, 5, 6])
b[2]=-10
b
array([ 3, 4, -10, 6])
a
array([ 0, 1, 2, 3, 4, -10, 6, 7, 8, 9])
id(b)
1829350963400
数据的浅拷贝与深拷贝
1.深浅拷贝都是对源对象的复制,占用不同的内存空间。
2.不可变类型的对象,对于深浅拷贝毫无影响,最终的地址值和值都是相等的。
3.可变类型的对象:值相等,地址不相等 。
**浅拷贝 **
定义:浅拷贝是对另外一个变量的内存地址的拷贝,这两个变量指向同一个内存地址的变量值。
共享内存地址的两个变量,当其中一个变量的值改变时另一个变量的值也随之改变。此时,变量间的“搓”是
“浅拷贝”
a=np.array([-45,-66,2,25,-33])
b=a
b is a#True
id(a)#2150984309776
id(b)#2150984309776
a==b
array([ True, True, True, True, True])
a[0]=6
a
array([ 6, -66, 2, 25, -33])
b
array([ 6, -66, 2, 25, -33])
#如果内存地址不一样
c=np.array([-45,-66,2,99,-33])
d=np.array([-45,-66,2,99,-33])
id(c)#2150984309776
id(d)#2150984307600
c==d
array([ True, True, True, True, True])
c[1]=666
c
array([-45, 666, 2, 99, -33])
d
array([-45, -66, 2, 99, -33])
浅拷贝-ndarray.view()
共享“视图”(view)的两个变量,当其中一个变量的值改变时,另一个变量的值也随之改变此时,变量间的“拷贝”也是“浅拷贝”
e=np.array([-45,-66,2,25,99,-33])
f=e.view()#f与e“共享视图”
id(e)
1829592944464
id(f)
1829592993928
f.shape=(2,3)
f
array([[-45, -66, 2],
[ 25, 99, -33]])
e[0]=0
e
array([ 0, -66, 2, 25, 99, -33])
f
array([[ 0, -66, 2],
[ 25, 99, -33]])
f[1,1]=88
f
array([[ 0, -66, 2],
[ 25, 88, -33]])
e
array([ 0, -66, 2, 25, 88, -33])
深拷贝
Nummpy中的深拷贝—np.copy
定义:一个变量对另外一个变量的值拷贝。
注:拷贝的是目标变量的值,是真实的拷贝,新的变量产生了新的内存地址。
通过“深拷贝”得到的变量互不干扰,其中一个变量的值改变时,不影响其他变量的值。
e
array([ 0, -66, 2, 25, 88, -33])
g=np.copy(e)
g
array([ 0, -66, 2, 25, 88, -33])
e[0]=8
e
array([ 8, -66, 2, 25, 88, -33])
g
array([ 0, -66, 2, 25, 88, -33])
id(e)
1829592944464
id(g)
1829592943672
-
存取元素
存取元素中的“浅拷贝”与“深拷贝”
使用整数序列
当使用整数序列对数组元素进行存取时,将使用整数序列中的每个元素作为下标,整数序列可以是列表或者数组。使用整数序列作为下标获得的数组不和原始数组共享数据空间。
x=np.arange(10,1,-1)
x
array([10, 9, 8, 7, 6, 5, 4, 3, 2])
x[[3,3,1,8]]
array([7, 7, 9, 2])
b=x[np.array([3,3,-3,8])]
b
array([7, 7, 4, 2])
b[2]=100
b
array([ 7, 7, 100, 2])
x #由于b和lx不共享数据空间,因此x中的值并没有改变b
array([10, 9, 8, 7, 6, 5, 4, 3, 2])
x[[3,5,1]] = -1,-2,-3 #整数序列下标也可以用来修改元素的值
x
array([10, -3, 8, -1, 6, -2, 4, 3, 2])
- 当使用布尔数组b作为下标存取数组x中的元素时,将收集数组x中所有在数组b中对应下标为True的元素。使用布尔数组作为下标获得的数组不和原始数组共享数据空间,注意这种方式只对应于布尔数组,不能使用布尔列表。
x=np.arange(5,0,-1)
x
array([5, 4, 3, 2, 1])
x[np.array([True,False,True,False,False])]#布尔数组中下标为0,2的元素为True,因此获取x中下标为0,2的元素
array([5, 3])
x[np.array([True,False,True,True,False])] =-1,-2,-3#布尔数组下标也可以用来修改元素
x
array([-1, 4, -2, -3, 1])
x=np.random.rand(10)#产生一个长度为10,元素值为0-1的随机数的数组
x
array([0.30361704, 0.06640523, 0.1108192 , 0.28438393, 0.81049677,
0.30720847, 0.73616764, 0.95115896, 0.76405874, 0.75693159])
x[x>0.5]
array([0.81049677, 0.73616764, 0.95115896, 0.76405874, 0.75693159])
- np.asarray()与np.array()的区别
在numpy中,asarray()函数与array()函数都可迭代对象转换为ndarray类型,它们之间的区别是:
1.当传入的参数是list等一般数组类型时,两者没有区别
a=[1,2,3]
b1=np.array(a) 深拷贝
b2=np.asarray(a)
a[0]=4
print(a)
print(b1)
print(b2)
输入:
[4,2,3]
[1,2,3]
[1,2,3]
2.当传入参数是ndarray类型时,array()函数会拷贝原数据,开辟新的内存在储存它,就是新建了一个ndarray对象。而asarray与原参数共享容一个内存
a = np.arange(3)
bl = np.array (a)
b2 = np.asarray (a)
a[0]=4
print(a)
print(bl)
print(b2)
输出:
[4 1 2]
[0 1 2]
[4 1 2]
从asarray()的源代码也可以看出asarray()和array()的区别:
def asarray (a,dtype-None,order=None,*, like=None):
if like is not None:
return _ asarray_with_like(a,dtype=dtype,order=order,like=like)
return array(a,dtype,copy=False,order=order)
还可以改变 array()函数的copy参数来控制它是否拷贝传入的数组