Python3:迭代二进制字符串将字符转换为整数

时间:2017-04-08 17:21:25

标签: python string python-2.7 python-3.x iteration

我觉得我在这里遗漏了一些小事:

我最近跳转到Python3(在Eclipse中使用PyDev) 我有一个计算熵值的项目,并包含以下代码:

data = b'NVGI\x19\x01\x10\x00'
seen = dict(((chr(x), 0) for x in range(0,256)))
for byte in data:
    seen[byte]+=1

数据中的二进制字符串要长得多,但这足以用于演示目的。

使用python3,此代码会导致KeyError。使用python2.7,这一切都没有问题。

这是因为迭代数据会返回一个整数(在这种情况下为78),而看到则需要一个字符'N'。

奇怪的是,在python2.7中,相同的代码将生成预期的字符“N”。

我现在已经通过以下方式帮助了这个:

seen[ord(byte)] += 1

有人可以尝试复制或告诉我哪里出错了吗?

1 个答案:

答案 0 :(得分:4)

因为在中,二进制字符串的元素为int s

事实上:

>>> type(data[0])
<class 'int'>

这也在"What's New In Python 3.0" documentation中指定。

所以你可以通过例如构建字典来解决问题,如:

seen = dict(((x, 0) for x in range(0,256)))

或者你可以用相反的方式

data = b'NVGI\x19\x01\x10\x00'
seen = dict(((chr(x), 0) for x in range(0,256)))
for byte in data:
    seen[chr(byte)]+=1

但更优雅的解决方案是简单地使用计数器:

from collections import Counter

result = Counter(data)

生成:

>>> Counter(data)
Counter({16: 1, 1: 1, 86: 1, 25: 1, 73: 1, 71: 1, 78: 1, 0: 1})

Counterdict子类,因此计数器支持所有字典操作。

如果您希望计数器包含str值,您可以这样做:

result = Counter(chr(x) for x in data)

这给出了:

>>> Counter(chr(x) for x in data)
Counter({'\x00': 1, 'G': 1, 'I': 1, '\x01': 1, 'V': 1, 'N': 1, '\x10': 1, '\x19': 1})

请注意,如果您查询不存在的密钥的计数器,它将返回0 。因此,您也可以节省内存,因为您不一定要计算所有256个值。