NumPy学习笔记18.字节交换;副本和视图

mac2024-03-29  34

1.NumPy字节交换

存储在计算机内存中的数据取决于 CPU 使用的架构。 它可以是小端(最小有效位存储在最小地址中)或大端(最小有效字节存储在最大地址中)。

import numpy as np a = np.array([1,256,8755],dtype = np.int16) print('数组是:') print(a) print('以十六进制表示内存中的数据:') print(map(hex,a)) # byteswap()函数通过传入true原地交换 print('调用byteswap()函数:') print(a.byteswap(True)) print('十六进制形式:') print(map(hex,a)) # 字节已经交换了 数组是: [ 1 256 8755] 以十六进制表示内存中的数据: <map object at 0x000001AC1B7C0048> 调用byteswap()函数: [ 256 1 13090] 十六进制形式: <map object at 0x000001AC21A5DD30>

2.NumPy副本和视图

副本是一个数据的完整的拷贝,如果对副本修改,不会影响到原始数据,物理内存不在同一位置。 视图是数据的一个别称或引用,通过该别称或引用也可访问、操作原有数据,但原有数据不会产生拷贝。如果对视图进行修改,它会影响原始数据,物理内存在同一位置。

视图一般发生在:

numpy的切片操作返回原有数据的视图调用ndarray的view()函数产生一个视图

副本一般发生在:

Python序列的切片操作,调用deepCopy()函数调用ndarray的copy()函数产生一个副本

无复制 简单的赋值不会创建数组对象的副本。相反,它使用原始数组的相同id()来访问它,id()返回Python对象的通用标识符,类似于C中的指针。 此外,一个数组的任何变化都反映在另一个数组上,比如:一个数组的形状改变也会改变另一个数组的形状。

import numpy as np a = np.arange(6) print('数组是:') print(a) print('调用id()函数:') print(id(a)) print('a赋值给b:') b = a print(b) print('b拥有相同id():') print(id(b)) print('修改b的形状:') b.shape = 3,2 print(b) print('a的形状也修改了:') print(a) 数组是: [0 1 2 3 4 5] 调用id()函数: 1838811079744 a赋值给b: [0 1 2 3 4 5] b拥有相同id(): 1838811079744 修改b的形状: [[0 1] [2 3] [4 5]] a的形状也修改了: [[0 1] [2 3] [4 5]]
视图或浅拷贝

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(): 1838811079984 b 的 id(): 1838811079904 b 的形状: [[0 1 2] [3 4 5]] a 的形状: [[0 1] [2 3] [4 5]] # 使用切片创建视图修改数据会影响到原始数组: import numpy as np arr = np.arange(12) print('数组是:') print(arr) print('创建切片:') a = arr[3:] b = arr[3:] a[1] = 123 b[2] = 234 print(arr) print(id(a),id(b),id(arr[3:])) 数组是: [ 0 1 2 3 4 5 6 7 8 9 10 11] 创建切片: [ 0 1 2 3 123 234 6 7 8 9 10 11] 1838811079664 1838811079984 1838811079824

变量a,b都是arr的一部分视图,对视图的修改会直接反映到原数据中,但观察a,b的id,是不同的,也就是说:视图虽然指向原数据,但是它们和赋值引用还是有区别的。

副本或深拷贝

ndarray.copy()函数创建一个副本,对副本数据进行修改,不会影响到原始数据,它们物理内存不在同一个位置。

import numpy as np a = np.array([[10,10],[2,3],[4,5]]) print('数组a:') print(a) print('创建a的深层副本:') b = a.copy() print('数组b:') print(b) # b与a不共享任何内容 print('可以通过写入b来写入a吗?') print(b is a) print('修改b的内容:') b[0,0] = 100 print('修改后的数组b:') print(b) print('a保持不变:') print(a) 数组a: [[10 10] [ 2 3] [ 4 5]] 创建a的深层副本: 数组b: [[10 10] [ 2 3] [ 4 5]] 可以通过写入b来写入a吗? False 修改b的内容: 修改后的数组b: [[100 10] [ 2 3] [ 4 5]] a保持不变: [[10 10] [ 2 3] [ 4 5]]
深浅拷贝

在Python中,对象赋值实际上是对象的引用,当创建一个对象,然后把它赋给另一个变量的时候,Python并没有拷贝这个对象,而只是拷贝了这个对象的引用,称之为浅拷贝。 在Python中,当进行赋值操作时,为了使两个变量互补影响,可以使用copy模块中的deepcopy方法,称之为深拷贝。 append()函数: 当list类型的对象进行append操作时,实际上追加的是该对象的引用。 id()函数: 返回对象的唯一标识,可以类比成该对象在内存中的地址。

alist = [] num = [2] alist.append(num) id(num) == id(alist[0])

结果为True 但当num发生改变时(前提是id(num)不发生改变),alist的内容也随之发生变化,往往会带来意想不到的后果,想避免这种情况,可以采用深拷贝解决:

alist.append(copy.deepcopy(num))

学习参考:

菜鸟教程:https://www.runoob.com/numpy/numpy-tutorial.html
最新回复(0)