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 å�‚数。