lar*_*sks 11 python python-2.x python-3.x
结果比我想象的更棘手.我有一个字节串:
data = b'abcdefghijklmnopqrstuvwxyz'
Run Code Online (Sandbox Code Playgroud)
我想以n个字节的块来读取这些数据.在Python 2下,使用文档中对grouper配方的一个小修改,这是微不足道的itertools:
def grouper(iterable, n, fillvalue=None):
"Collect data into fixed-length chunks or blocks"
# grouper('ABCDEFG', 3, 'x') --> ABC DEF Gxx
args = [iter(iterable)] * n
return (''.join(x) for x in izip_longest(fillvalue=fillvalue, *args))
Run Code Online (Sandbox Code Playgroud)
有了这个,我可以打电话:
>>> list(grouper(data, 2))
Run Code Online (Sandbox Code Playgroud)
得到:
['ab', 'cd', 'ef', 'gh', 'ij', 'kl', 'mn', 'op', 'qr', 'st', 'uv', 'wx', 'yz']
Run Code Online (Sandbox Code Playgroud)
在Python 3下,这变得更加棘手.grouper写的函数简单地落在:
>>> list(grouper(data, 2))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 5, in <genexpr>
TypeError: sequence item 0: expected str instance, int found
Run Code Online (Sandbox Code Playgroud)
这是因为在Python 3中,当你遍历一个bytestring(比如b'foo')时,你得到一个整数列表,而不是一个字节列表:
>>> list(b'foo')
[102, 111, 111]
Run Code Online (Sandbox Code Playgroud)
python 3 bytes函数将在这里提供帮助:
def grouper(iterable, n, fillvalue=None):
"Collect data into fixed-length chunks or blocks"
# grouper('ABCDEFG', 3, 'x') --> ABC DEF Gxx
args = [iter(iterable)] * n
return (bytes(x) for x in izip_longest(fillvalue=fillvalue, *args))
Run Code Online (Sandbox Code Playgroud)
使用它,我得到我想要的:
>>> list(grouper(data, 2))
[b'ab', b'cd', b'ef', b'gh', b'ij', b'kl', b'mn', b'op', b'qr', b'st', b'uv', b'wx', b'yz']
Run Code Online (Sandbox Code Playgroud)
但是(当然!)bytesPython 2下的函数行为方式不同.它只是一个别名str,因此导致:
>>> list(grouper(data, 2))
["('a', 'b')", "('c', 'd')", "('e', 'f')", "('g', 'h')", "('i', 'j')", "('k', 'l')", "('m', 'n')", "('o', 'p')", "('q', 'r')", "('s', 't')", "('u', 'v')", "('w', 'x')", "('y', 'z')"]
Run Code Online (Sandbox Code Playgroud)
......这根本没用.我最后写了以下内容:
def to_bytes(s):
if six.PY3:
return bytes(s)
else:
return ''.encode('utf-8').join(list(s))
def grouper(iterable, n, fillvalue=None):
"Collect data into fixed-length chunks or blocks"
# grouper('ABCDEFG', 3, 'x') --> ABC DEF Gxx
args = [iter(iterable)] * n
return (to_bytes(x) for x in izip_longest(fillvalue=fillvalue, *args))
Run Code Online (Sandbox Code Playgroud)
这似乎有效,但这真的是这样做的方法吗?
Funcy(一个提供各种有用实用程序的库,同时支持 Python 2 和 3)提供了一个chunks功能:
>>> import funcy
>>> data = b'abcdefghijklmnopqrstuvwxyz'
>>> list(funcy.chunks(6, data))
[b'abcdef', b'ghijkl', b'mnopqr', b'stuvwx', b'yz'] # Python 3
['abcdef', 'ghijkl', 'mnopqr', 'stuvwx', 'yz'] # Python 2.7
Run Code Online (Sandbox Code Playgroud)
或者,您可以在程序中包含一个简单的实现(与 Python 2.7 和 3 兼容):
def chunked(size, source):
for i in range(0, len(source), size):
yield source[i:i+size]
Run Code Online (Sandbox Code Playgroud)
它的行为相同(至少对于您的数据;Funcychunks也适用于迭代器,但不能):
>>> list(chunked(6, data))
[b'abcdef', b'ghijkl', b'mnopqr', b'stuvwx', b'yz'] # Python 3
['abcdef', 'ghijkl', 'mnopqr', 'stuvwx', 'yz'] # Python 2.7
Run Code Online (Sandbox Code Playgroud)