目录
Numpy中的深拷贝、浅拷贝和视图
什么是拷贝?
所谓拷贝,就是赋值。把一个变量赋给另外一个变量,就是把变量的内容进行拷贝。把一个对象的值赋给另外一个对象,就是把一个对象拷贝一份。
1.深拷贝--np.copy()
通过”深拷贝“得到的变量互不干扰,其中一个变量的值改变时,不影响其他变量的值。
深拷贝的特点:
- 变量的内存地址不同;
- 变量各有自己的值,且互不影响;
- 对其任意一个变量的值的改变不会影响其余变量的值;
import numpy as np
a = np.arange(6)
print('深拷贝')
d = a.copy()
print('a:',a)
print('d:',d)
# 将a的第2个元素值也更改
a[1] = 5
print('赋值后:')
print('a:',a,id(a))
print('d:',d,id(d))
"""
深拷贝
a: [0 1 2 3 4 5]
d: [0 1 2 3 4 5]
赋值后:
a: [0 5 2 3 4 5] 1909599773104
d: [0 1 2 3 4 5] 1909599598608
"""
>>> d = a.copy() # 创建了新的数组和新的数据
>>> d is a
False
>>> d.base is a # d没有和a共享任何数据
False
2.浅拷贝
共享内存地址的两个变量,当其中一个变量的值改变时,另一个变量的值也随之改变。此时,变量间的“拷贝”是“浅拷贝”
共享“视图”(view)的两个变量,当其中一个变量的值改变时,另一个变量的值也随之改变。此时,变量间的“拷贝”也是“浅拷贝”
浅拷贝的特点:
- 公用一个值;
- 这两个变量的内存地址一样;
- 对其中一个变量的值改变,另外一个变量的值也会改变;
切片操作是特殊的 浅拷贝;(注意与python的list切片使用是深拷贝,这是一种特殊的浅拷贝,因为出现了新的内存地址,但是数据修改仍会同步)
直接赋值给另一个变量是 浅拷贝。
print('浅拷贝')
#1、直接赋值法
b = a
#2、切片法
c = a[:]
print('a:',a)
print('b:',b)
print('c:',c)
print('改变b的第1个位置上的元素之后———')
# 改变a中第一个元素的值
a[0] = 4
c[2] = 7
print('a:',a,id(a))
print('b:',b,id(b))
print('c:',c,id(c))
"""
一、浅拷贝
a: [0 5 2 3 4 5]
b: [0 5 2 3 4 5]
c: [0 5 2 3 4 5]
改变b的第1个位置上的元素之后———
a: [4 5 7 3 4 5] 1909599773104
b: [4 5 7 3 4 5] 1909599773104
c: [4 5 7 3 4 5] 1909599599760 #numpy中的切片的使用比较特殊,会发现存储地址已经发出变化,但是a和c之间仍然会相互影响,所以这是一种特殊的浅拷贝。
"""
3.视图view()
视图是数据的一个别称或引用,通过该别称或引用亦便可访问、操作原有数据,但原有数据不会产生拷贝。如果我们对视图进行修改,它会影响到原始数据,物理内存在同一位置。
视图一般发生在:
-
1、numpy的切片操作返回原数据的视图。
-
2、调用ndarray的view()函数产生一个视图。
ndarray.view() 方法会创建一个新的数组对象,该方法创建的新数组的维数更改不会更改原始数据的维数。
import numpy as np
# 最开始 a 是个 3X2 的数组
a = np.arange(6).reshape(3, 2)
print('数组 a:')
print(a)
print('创建 a 的视图:')
b = a.view()
print(b)
print('两个数组的 id() 不同:')
print('a 的 id():')
print(id(a))
print('b 的 id():')
print(id(b))
# 修改 b 的形状,并不会修改 a
b.shape = 2, 3
print('b 的形状:')
print(b)
print('a 的形状:')
print(a)
运行结果:
数组 a:
[[0 1]
[2 3]
[4 5]]
创建 a 的视图:
[[0 1]
[2 3]
[4 5]]
两个数组的 id() 不同:
a 的 id():
1909594761328
b 的 id():
1909600033552
b 的形状:
[[0 1 2]
[3 4 5]]
a 的形状:
[[0 1]
[2 3]
[4 5]]