问题
python编程中用到通讯,也自然需要用到字符串转list功能,试过了很多方法均不理想,最后不得已用了神通广大的eval()
具体如下:
str0 = b'[[0], [486.13334690553745, 473.83448697068405, 7.678963807368689]],[[1], [504.08351648351646], 256.98362637362635],[[2], []],[[3], []]'
要将这一个字符串,转为list或ndarray,维度不定,长度也不定,里面内容不是int,而是float。
网上找到很多方法,但都有局限,最后要么是维度限制,要么是长度限制,要么是int限制,要么就不能识别方括号。
实现
最后一句话搞定:
temp1 = eval(str1)
运行结果:
([[0], [486.13334690553745, 473.83448697068405, 7.678963807368689]], [[1], [504.08351648351646], 256.98362637362635], [[2], []], [[3], []])
看不出来转换情况哈,那么打断点,看temp1这个变量的数据结构,见下图
最深层的数据类型是float,结构层次也OK。结果满意。
隐患
为什么又说是不得已才用eval()呢,因为这个函数太神奇了,它是运行括号中的内容,也就是将其当作一个表达式来运行的,这里面就有一个隐患,如果通讯的对方是一个恶意程序,将恶意代码隐藏到通讯内容中,那么eval的运行结果是不可知的。
解决方案
解决方法也有,对于我的这个通讯内容,用到了0到9的数字,空格,小数点,逗号,方括号,那么我就可以将除了这些的其他所有符号,英文字母都去除,以去除隐患。
使用正则表达式,全代码如下:
import re
str0 = b'[[0], [486.13334690553745, 473.83448697068405, 7.678963807368689]],[[1], [504.08351648351646], 256.98362637362635],[[2], []],[[3], []]'
str0 = str0.decode('utf-8') # 去除前面那个b
str1 = re.sub('([^\u0030-\u0039\u005b\]\u002c\u002e])', '', str0)
temp1 = eval(str1)
print(temp1)
在print这一句打断点,debug运行,可以看到temp1的内容,和之前是一样的。
下面对正则表达式说明一下:
re.sub('([^\u0030-\u0039\u005b\]\u002c\u002e])', '', str0)
sub表示提取子集
\u0030-\u0039表示ASCII码中30到39这一段,也就是数字0~9
\u005b表示左方括号 [
而右方括号不能这样表示,需要转义,即 \]
\u002c是逗号 ,
\u002e是小数点 .