写点什么

NumPy 的深浅拷贝的区别与选择

  • 2024-06-17
    湖南
  • 本文字数:1989 字

    阅读完需:约 7 分钟

大家好,我们知道中华上下五千年。习武之人不在少数。但是他们习武的类型也大概分成两种:一种是外功,主要学习手法,腿法等的力量和协调性;另一种是内功,主要锻炼的是气力,骨骼等内在的改变。

在学习 Numpy 库中的副本和视图的时候,接触到了其中有一个数据拷贝的选择,它跟习武的方式类似,分为深拷贝和浅拷贝。那么究竟他们有什么区别?如何进行选择?本文将带领我们一探究竟!

知道

首先,在研究深浅拷贝之前,得知道相关的一些概念这样,后面我们才能游刃有余。比如我们在看本文内容之前,你是否学习了 Python 基础,NumPy 环境是否已经安装完成。


好了,现在正式进入我们的内容。

什么是深拷贝?

深拷贝指在拷贝原数组的时候,会在内存中重新创建一个新的数组并且进行赋值,新数组中的元素进行任何操作的时候,是不会影响到原数组的,他们在数组中的内存 id 是不同的

什么是浅拷贝?

浅拷贝指在拷贝原数组的时候,它只不过是原数组的一个引用,并不会再内存中创建一个新的数组,所以在操作新数组中的元素的时候,原数组也是会跟着一起变化的,会影响到原数组的数组结构。


既然我们已经知道了什么是深拷贝,什么是浅拷贝。那么光凭理论是说不过去的,我们得进行实践。记得有一句话说的:“实践是检验真理的唯一途径”。那么我们开始吧!🧐

验证

首先我们得保证安装了 Pyhton 的编辑器,我用的是 PyCharm,没有的可以在官网自行下载安装。


这里 Numpy 库给我们提供的深拷贝的函数是 copy()函数,我们就使用这个函数进行验证。


先在编辑器中创建一个数组,并进行数组的深拷贝,查看结果如何?

"""@Created on : 2024/6/17 11:16@creator : er_nao@File :numpy_28_副本和视图.py@Description :"""
import numpy as np
# copy()函数的使用
x = np.arange(32).reshape(4, 8)print('原数组')print(x)# 获取数组在内存中的idprint('x数组的id: ')print(id(x))print('\n')# 将x数组copy给yy = x.copy()print('y数组的id:')print(id(y))print('\n')
# 修改y数组,测试x数组是否会发生变化y.shape = 8, 4print('打印y数组')print(y)print('\n')print('打印x数组')print(x)
# # 输出结果# 原数组# [[ 0 1 2 3 4 5 6 7]# [ 8 9 10 11 12 13 14 15]# [16 17 18 19 20 21 22 23]# [24 25 26 27 28 29 30 31]]# x数组的id: # 1972961081072# # # y数组的id:# 1973520214672# # # 打印y数组# [[ 0 1 2 3]# [ 4 5 6 7]# [ 8 9 10 11]# [12 13 14 15]# [16 17 18 19]# [20 21 22 23]# [24 25 26 27]# [28 29 30 31]]# # # 打印x数组# [[ 0 1 2 3 4 5 6 7]# [ 8 9 10 11 12 13 14 15]# [16 17 18 19 20 21 22 23]# [24 25 26 27 28 29 30 31]]
复制代码

我们可以看到,创建了一个原数组 x,然后将 x 数组深拷贝给新数组 y,输出的结果显而易见,x 在内容中的 id 和 y 的 id 是不一样的,显然这儿变成了两个不同的数组,然后使用 shape 函数,进行 y 数组的变化,输出结果是 y 数组格式已经变化,而原数组并没有收到影响。


下来我们验证浅拷贝,浅拷贝其实就比较简单了,就是数组之间的赋值。我们来看一下相关代码

# 传统数组之间相互赋值
x = np.array([1, 2, 3, 4, 5, 6, 7, 8])print('原数组')print(x)# 获取数组在内存中的idprint('x数组的id: ')print(id(x))print('\n')# 将x数组赋值给yy = xprint('y数组的id:')print(id(y))print('\n')# 修改y数组,测试x数组是否会发生变化y.shape = 2, 4print('打印y数组')print(y)print('\n')print('打印x数组')print(x)
# 输出结果# 原数组# [1 2 3 4 5 6 7 8]# x数组的id: # 1795409508176# # # y数组的id:# 1795409508176# # # 打印y数组# [[1 2 3 4]# [5 6 7 8]]# # # 打印x数组# [[1 2 3 4]# [5 6 7 8]]
复制代码

这次我们可以很清晰的看到,将 x 数组赋值给数组 y,改变数组 y 以后,x 也改变了。并且他们的内存 id 都是一样的。


其实 NumPy 库还给我们提供了一种浅拷贝的方法, 使用 view()函数进行拷贝。

# 创建原始数组arr = np.array([2, 4, 8, 12, 20])
# 使用view函数创建视图view_arr = arr.view()
# 修改原始数组中的元素arr[0] = 100
# 输出修改后的结果print("原数组id:", id(arr))print("视图数组id:", id(view_arr))print("原数组:", arr)print("视图数组:", view_arr)
# 输出结果# 原数组id: 1958732690896# 视图数组id: 1958732691280# 原数组: [100 4 8 12 20]# 视图数组: [100 4 8 12 20]
复制代码

我们发现,view()函数的是创建一个新的视图,但是它在元素内存的指向和原数组的相同的,改变原数值的元素,创建的视图元素也随之改变。

清楚

以上就是本文的全部内容,关于深浅拷贝如何进行选择, 我们需要根据实际的项目需求进行使用,选择正确的拷贝方式不但能够节省内存空间,而且在效率上也会大大提高,这也是我们在项目优化方面需要进行考虑的。

用户头像

欢迎关注,一起学习,一起交流,一起进步 2020-06-14 加入

公众号:做梦都在改BUG

评论

发布
暂无评论
NumPy的深浅拷贝的区别与选择_Python_我再BUG界嘎嘎乱杀_InfoQ写作社区