问题
你想在一个文件里每次读入固定大小的字节,比如每次读入4个字节并转成int,或者每次读入x个字节并进行结构化,例如:
l = [5, 2, 4, 1, 2, 4, 5, 6, 8]
with open('test', 'wb') as fd:
for num in l:
fd.write(num.to_bytes(4, 'big'))
解决方案
可以简单的用while
循环来完成
with open('test', 'rb') as fd:
r = fd.read(4)
while r:
print(int.from_bytes(r, 'big'), end=' ')
r = fd.read(4)
输出为5 2 4 1 2 4 5 6 8
但更优雅的做法是结合使用iter
和functools.partial
from functools import partial
with open('test', 'rb') as fd:
for r in iter(partial(fd.read, 4), b''):
print(int.from_bytes(r, 'big'), end=' ')
输出同样是5 2 4 1 2 4 5 6 8
讨论
functools.partial
的作用是对一个函数进行包装(可以将一些参数的值固定)并生成一个新的签名,例如:
>>> from functools import partial
>>> basetwo = partial(int, base=2)
>>> basetwo.__doc__ = 'Convert base 2 string to an int.'
>>> basetwo('10010')
18
functools.partial
的大致实现如下:
def partial(func, *args, **keywords):
def newfunc(*fargs, **fkeywords):
newkeywords = keywords.copy()
newkeywords.update(fkeywords)
return func(*args, *fargs, **newkeywords)
newfunc.func = func
newfunc.args = args
newfunc.keywords = keywords
return newfunc
而iter
的作用是当只有一个参数时,对这个对象进行迭代,所以这个对象必须实现__iter()__
或__getitem()__
方法,例如:
>>> l = [1, 2, 3, 4]
>>> for i in iter(l):
... print(i, end=' ')
...
>>> 1 2 3 4
但当有两个参数时,第一个参数必须是可调用的(比如函数),第二个参数是终止的值,当调用第一个参数返回的结果等于第二个参数时,迭代就停止了,例如:
with open('mydata.txt') as fp:
for line in iter(fp.readline, ''):
process_line(line)
所以综合两个方法来看上面的iter(partial(fd.read, 4), b'')
,就是每次调用fd.read(4)
直到返回一个空的bytes
来源
Python Cookbook
关注
欢迎关注我的微信公众号:python每日一练
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。