在进行数据传输的时候我们可能会遇到各种数据类型,而传输只支持字节串类型(bytes类型)的数据,因此我们需要想办法将各种数据类型都转换为字节串类型或者字符串类型(字符串类型可以通过encode转成字节串)
这次的讨论是如何将数组类型(ndarray类型)转换为字节串,这里给出两种方案:
一、通过tostring和fromstring转换
tostring会将数组直接转换成字节串,并且会损失类型信息(dtype)和维度信息(shape),因此在实际传输中,除了把字节串传输过去外,还需要把数组的dtype和shape传输过去
import numpy as np
a1 = np.array([[[1,2,3],[4,5,6],[7,8,9]],[[11,22,33],[44,55,66],[77,88,99]],[[111,222,333],[444,555,666],[777,888,999]]])
a1_dtype = str(a1.dtype)
a1_shape = str(a1.shape)
print(a1.dtype) # 说明a1的dtype为int32
print(a1.shape) # 说明维度信息为(3,3,3)
s = a1.tostring()
print(type(s)) # 可知这里直接将数组转换成了字节串bytes
# 下面三句效果一样
# a2 = np.fromstring(s,dtype=np.int32).reshape((3,3,3))
# a2 = np.fromstring(s,dtype=getattr(np,str(a1.dtype))).reshape(a1.shape)
a2 = np.fromstring(s,dtype=getattr(np,a1_dtype)).reshape(eval(a1_shape))
print(a2) # 转换成功
二、将数组转换为列表,列表再转换为字符串,再用eval取出列表
使用numpy里的tolist()方法可以彻底将数组转换成列表,而python中的eval()函数能从字符串中读取出list类型的数据,将整个字符串执行一遍并返回其结果
import numpy as np
a1 = np.array([[[1,2,3],[4,5,6],[7,8,9]],[[11,22,33],[44,55,66],[77,88,99]],[[111,222,333],[444,555,666],[777,888,999]]])
my_list1 = a1.tolist()
print(my_list1)
s = "np.array({})".format(my_list1)
a2 = eval(s)
print(a2)
这里对比一下tolist()和list()函数,tolist()函数能将数组彻底转换成列表,并且保留维度信息,而list()不行,list()只会讲数据转换成一维列表,列表里面的元素又是数组(该数组还是原数组转换成列表后再转换过来的数组)
示例:
import numpy as np
a1 = np.array([[[1,2,3],[4,5,6],[7,8,9]],[[11,22,33],[44,55,66],[77,88,99]],[[111,222,333],[444,555,666],[777,888,999]]])
my_list2 = list(a1)
print(my_list2)
结果:
[array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]]), array([[11, 22, 33],
[44, 55, 66],
[77, 88, 99]]), array([[111, 222, 333],
[444, 555, 666],
[777, 888, 999]])]
而该列表也能转换回数组:
a2 = np.array(my_list2)
print(a2)
但是将该列表转换为字符串后,eval无法识别出来
import numpy as np
a1 = np.array([[[1,2,3],[4,5,6],[7,8,9]],[[11,22,33],[44,55,66],[77,88,99]],[[111,222,333],[444,555,666],[777,888,999]]])
my_list2 = list(a1)
print(my_list2)
s = str(my_list2)
a2 = np.array(eval(s)) # 报错
print(a2)
错误信息:
NameError: name 'array' is not defined
因此list()方法要慎用