Ara*_*uma 2 python string iteration python-2.7 python-3.x
我觉得我在这里错过了一些微不足道的东西:
我最近跳到了 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
Run Code Online (Sandbox Code Playgroud)
data 中的二进制字符串要长得多,但这足以用于演示目的。
对于 python3,此代码会导致 KeyError。对于 python2.7,这完全没有问题。
这是因为迭代data返回一个整数(在本例中为 78),而saw需要一个字符“N”。
奇怪的是,在 python2.7 中,相同的代码将产生预期的字符“N”。
我现在已经通过这样做来创可贴:
seen[ord(byte)] += 1
Run Code Online (Sandbox Code Playgroud)
有人可以尝试复制这个或告诉我哪里出了问题吗?
因为在python-3中,二进制字符串的元素int是s。
的确:
>>> type(data[0])
<class 'int'>
Run Code Online (Sandbox Code Playgroud)
“ Python 3.0 的新增功能”文档中也对此进行了指定。
因此,您可以通过构建字典来解决问题,例如:
seen = dict(((x, 0) for x in range(0,256)))Run Code Online (Sandbox Code Playgroud)
或者你可以用相反的方式来做:
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)]+=1Run Code Online (Sandbox Code Playgroud)
但更优雅的解决方案是简单地使用计数器:
from collections import Counter
result = Counter(data)Run Code Online (Sandbox Code Playgroud)
生成:
>>> Counter(data)
Counter({16: 1, 1: 1, 86: 1, 25: 1, 73: 1, 71: 1, 78: 1, 0: 1})
Run Code Online (Sandbox Code Playgroud)
ACounter是的子类dict,因此计数器支持所有字典操作。
如果您希望计数器包含string 值,您可以这样做:
result = Counter(chr(x) for x in data)Run Code Online (Sandbox Code Playgroud)
这给出:
>>> Counter(chr(x) for x in data)
Counter({'\x00': 1, 'G': 1, 'I': 1, '\x01': 1, 'V': 1, 'N': 1, '\x10': 1, '\x19': 1})
Run Code Online (Sandbox Code Playgroud)
请注意,如果您在计数器中查询不存在的键,它将返回0。因此,您还可以节省内存,因为您不一定拥有所有 256 个值的计数。