目录

Numpy中的深拷贝、浅拷贝和视图

什么是拷贝?

1.深拷贝--np.copy()

深拷贝的特点:

2.浅拷贝

浅拷贝的特点:

3.视图view()


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]]