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

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

学习参考:

发布了61 篇原创文章 · 获赞 7 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/MRZHUGH/article/details/102834208
18.
今日推荐