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))
学习参考: