4.8 跳过å�¯è¿ä»£å¯¹è±¡çš„开始部分¶
问题¶
ä½ æƒ³é��历一个å�¯è¿ä»£å¯¹è±¡ï¼Œä½†æ˜¯å®ƒå¼€å§‹çš„æŸ�äº›å…ƒç´ ä½ å¹¶ä¸�感兴趣,想跳过它们。
解决方案¶
itertools 模å�—䏿œ‰ä¸€äº›å‡½æ•°å�¯ä»¥å®Œæˆ�这个任务。
首先介ç»�的是 itertools.dropwhile() å‡½æ•°ã€‚ä½¿ç”¨æ—¶ï¼Œä½ ç»™å®ƒä¼ é€’ä¸€ä¸ªå‡½æ•°å¯¹è±¡å’Œä¸€ä¸ªå�¯è¿ä»£å¯¹è±¡ã€‚
它会返回一个è¿ä»£å™¨å¯¹è±¡ï¼Œä¸¢å¼ƒåŽŸæœ‰åº�列ä¸ç›´åˆ°å‡½æ•°è¿”回Flase之å‰�çš„æ‰€æœ‰å…ƒç´ ï¼Œç„¶å�Žè¿”回å�Žé�¢æ‰€æœ‰å…ƒç´ 。
为了演示,å�‡å®šä½ 在读å�–ä¸€ä¸ªå¼€å§‹éƒ¨åˆ†æ˜¯å‡ è¡Œæ³¨é‡Šçš„æº�文件。比如:
>>> with open('/etc/passwd') as f:
... for line in f:
... print(line, end='')
...
##
# User Database
#
# Note that this file is consulted directly only when the system is running
# in single-user mode. At other times, this information is provided by
# Open Directory.
...
##
nobody:*:-2:-2:Unprivileged User:/var/empty:/usr/bin/false
root:*:0:0:System Administrator:/var/root:/bin/sh
...
>>>
å¦‚æžœä½ æƒ³è·³è¿‡å¼€å§‹éƒ¨åˆ†çš„æ³¨é‡Šè¡Œçš„è¯�,å�¯ä»¥è¿™æ ·å�šï¼š
>>> from itertools import dropwhile
>>> with open('/etc/passwd') as f:
... for line in dropwhile(lambda line: not line.startswith('#'), f):
... print(line, end='')
...
nobody:*:-2:-2:Unprivileged User:/var/empty:/usr/bin/false
root:*:0:0:System Administrator:/var/root:/bin/sh
...
>>>
这个例å�æ˜¯åŸºäºŽæ ¹æ�®æŸ�ä¸ªæµ‹è¯•å‡½æ•°è·³è¿‡å¼€å§‹çš„å…ƒç´ ã€‚
å¦‚æžœä½ å·²ç»�明确知é�“了è¦�è·³è¿‡çš„å…ƒç´ çš„åº�å�·çš„è¯�,那么å�¯ä»¥ä½¿ç”¨ itertools.islice() æ�¥ä»£æ›¿ã€‚比如:
>>> from itertools import islice
>>> items = ['a', 'b', 'c', 1, 4, 10, 15]
>>> for x in islice(items, 3, None):
... print(x)
...
4
10
15
>>>
在这个例å�ä¸ï¼Œ islice() 函数最å�Žé‚£ä¸ª None å�‚æ•°æŒ‡å®šäº†ä½ è¦�跳过å‰�é�¢3ä¸ªå…ƒç´ ï¼ŒèŽ·å�–第4个到最å�Žçš„æ‰€æœ‰å…ƒç´ ,
如果 None å’Œ3çš„ä½�置对调,æ„�æ€�就是仅仅获å�–å‰�ä¸‰ä¸ªå…ƒç´ æ�°æ�°ç›¸å��,
(这个跟切片的相å��æ“�作 [3:] å’Œ [:3] 原ç�†æ˜¯ä¸€æ ·çš„)。
讨论¶
函数 dropwhile() å’Œ islice() 其实就是两个帮助函数,为的就是é�¿å…�写出下é�¢è¿™ç§�冗余代ç �:
with open('/etc/passwd') as f:
# Skip over initial comments
while True:
line = next(f, '')
if not line.startswith('#'):
break
# Process remaining lines
while line:
# Replace with useful processing
print(line, end='')
line = next(f, None)
跳过一个å�¯è¿ä»£å¯¹è±¡çš„开始部分跟通常的过滤是ä¸�å�Œçš„。 比如,上述代ç �的第一个部分å�¯èƒ½ä¼šè¿™æ ·é‡�写:
with open('/etc/passwd') as f:
lines = (line for line in f if not line.startswith('#'))
for line in lines:
print(line, end='')
è¿™æ ·å†™ç¡®å®žå�¯ä»¥è·³è¿‡å¼€å§‹éƒ¨åˆ†çš„æ³¨é‡Šè¡Œï¼Œä½†æ˜¯å�Œæ ·ä¹Ÿä¼šè·³è¿‡æ–‡ä»¶ä¸å…¶ä»–所有的注释行。 æ�¢å�¥è¯�讲,我们的解决方案是仅仅跳过开始部分满足测试æ�¡ä»¶çš„行,在那以å�Žï¼Œæ‰€æœ‰çš„å…ƒç´ ä¸�å†�进行测试和过滤了。
最å�Žéœ€è¦�ç�€é‡�强调的一点是,本节的方案适用于所有å�¯è¿ä»£å¯¹è±¡ï¼ŒåŒ…括那些事先ä¸�能确定大å°�的, 比如生æˆ�器,文件å�Šå…¶ç±»ä¼¼çš„对象。