我不会解释为什么你的代码不起作用以及如何修复它(因为 Tim Pietzcker 已经做了令人钦佩的工作),我将解释如何编写代码,这样这样的问题就不会出现在第一名。
尝试编写自己的显式循环、检查和索引变量是困难且容易出错的。这就是为什么 Python 为您提供了几乎总是不需要这样做的好工具的原因。这就是你使用 Python 而不是 C 的原因。
例如,查看您的程序的以下版本:
count = 10
with open('/Users/abc/testfile.txt', 'r') as testfile:
for i, line in enumerate(testfile):
print line
if (i + 1) % count == 0:
if raw_input('Print More..') not in ['y', 'Y']:
break
这比原始代码更短,而且效率也更高(无需读取整个文件然后提前构建一个巨大的列表),但这些并不是使用它的好理由。
一个很好的理由是它更加健壮。这里几乎没有明确的循环逻辑会出错。你甚至不需要记住切片是如何工作的(当然,很容易知道它们[start:stop]
不是[start:length]
……但是如果你用另一种语言编程比 Python 更频繁,而且你总是在写s.sub(start, length)
,你会忘记…)。当您到达文件末尾时,它还会自动处理结束,而不是永远继续,为您关闭文件(即使在异常情况下,手动正确处理也很痛苦),以及您尚未编写的其他内容.
另一个很好的理由是它更容易阅读,因为代码尽可能多地告诉你它在做什么,而不是它如何做的细节。
但它仍然不完美,因为仍有一件事你很容易出错:那(i + 1) % count == 0
一点。事实上,我在第一次尝试时就弄错了(我忘记了 +1,所以它在第 0、10、20 行……而不是 9、19、29……之后给了我一个“更多”提示)。如果你有一个grouper
函数,你可以更简单、更健壮地重写它:
with open('/Users/abc/testfile.txt', 'r') as testfile:
for group in grouper(testfile, 10):
for line in group:
print line
if raw_input('Print More..') not in ['y', 'Y']:
break
或者,甚至更好:
with open('/Users/abc/testfile.txt', 'r') as testfile:
for group in grouper(testfile, 10):
print '\n'.join(group)
if raw_input('Print More..') not in ['y', 'Y']:
break
不幸的是,模块中没有内置这样的 grouper 函数itertools
,但你可以很容易地编写一个:
def grouper(iterator, size):
return itertools.izip(*[iterator]*size)
(如果效率很重要,请在这个网站上搜索——有几个问题,人们会深入比较达到相同效果的不同方法。但通常没关系。就此而言,如果你想了解为什么会这样对事物进行分组,请搜索此站点,因为它已至少解释过两次。)