4.16 迭代器代替while无�循环¶

问题¶

你在代�中使用 while 循环�迭代处�数�,因为它需�调用�个函数或者和一般迭代模���的测试�件。 能�能用迭代器��写这个循环呢?

解决方案¶

一个常�的IO�作程��能会想下�这样:

CHUNKSIZE = 8192

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

这�代�通常�以使用 iter() �代替,如下所示:

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

如果你怀疑它到底能�能正常工作,�以试验下一个简�的例�。比如:

>>> import sys
>>> f = open('/etc/passwd')
>>> for chunk in iter(lambda: f.read(10), ''):
...     n = sys.stdout.write(chunk)
...
nobody:*:-2:-2:Unprivileged User:/var/empty:/usr/bin/false
root:*:0:0:System Administrator:/var/root:/bin/sh
daemon:*:1:1:System Services:/var/root:/usr/bin/false
_uucp:*:4:4:Unix to Unix Copy Protocol:/var/spool/uucp:/usr/sbin/uucico
...
>>>

讨论¶

iter 函数一个鲜为人知的特性是它接�一个�选的 callable 对象和一个标记(结尾)值作为输入�数。 当以这�方�使用的时候,它会创建一个迭代器, 这个迭代器会�断调用 callable 对象直到返回值和标记值相等为止。

这�特殊的方法对于一些特定的会被��调用的函数很有效果,比如涉�到I/O调用的函数。 举例�讲,如果你想从套接字或文件中以数��的方�读�数�,通常你得��断��的执行 read() 或 recv() , 并在��紧跟一个文件结尾测试�决定是�终止。这节中的方案使用一个简�的 iter() 调用就�以将两者结�起�了。 其中 lambda 函数�数是为了创建一个无�的 callable 对象,并为 recv 或 read() 方法�供了 size �数。