内建函数iter(),第三个参数哨兵用法

循环读取文件常见写法

CHUNKSIZE=8192
def reader(s):
  while True:
    data = s.recv(CHUNKSIZE)
    if data == b'':
        break
    process_data(data)

iter()写法

def reader(s):
  for chunk in iter(lambda: s.recv(CHUNKSIZE), b''):
    process_data(data)

测试

import sys
f = open('/etc/passwd')
for chunk in iter(lambda: f.read(10), ''):
  n = sys.stdout.write(chunk)

讨论

关于内建函数iter(),一个少有人知的特性是它可以选择性接受一个无参的可调用对象
以及一个哨兵(结束)值作为输入。当以这种方式使用时,iter()会创建一个迭代器,
然后重复调用用户提供的可调用对象,直到它返回哨兵值为止。
这种特定的方式对于需要重复调用函数的情况,比如这些涉及I/O 的问题,有很好的效
果。比如,如果想从socket 或文件中按块读取数据,通常会重复调用read()或者recv(),
然后紧跟着检测是否到达文件结尾。而我们给出的解决方案简单地将这两个功能合并
为一个单独的iter()调用。解决方案中对lambda 的使用是为了创建一个不带参数的可调
用对象,但是还是可以对recv()或read()提供所需要的参数。

其它示例

from functools import partial
RECORD_SIZE = 32
with open("somefile.data", 'rb') as f:
  records = iter(partial(f.read, RECORD_SIZE), b'')
  for r in records:

讨论

关于iter()函数,一个少有人知的特性是,如果传递一个可调用对象及一个哨兵值给它,那么它
可以创建一个迭代器。得到的迭代器会重复调用用户提供的可迭代对象,直到返回的值为哨兵值
为止,此时迭代过程停止。
functools.partial用来创建可调用对象,每次调用它时都从文件中读取固定的字节数。b''在这里
用作哨兵值,当读取到文件结尾时就会返回这个值,此时迭代过程结束。

posted @ 2022-06-29 18:05  我在路上回头看  阅读(70)  评论(0)    收藏  举报