我觉得我在这里遗漏了一些小事:
我最近跳转到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
有人可以尝试复制或告诉我哪里出错了吗?
答案 0 :(得分:4)
因为在python-3中,二进制字符串的元素为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})
Counter
是dict
的子类,因此计数器支持所有字典操作。
如果您希望计数器包含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个值。