2

我想逐行读取python中的文件,但在某些情况下(基于if条件)我也想读取文件中的下一行,然后继续以相同的方式读取它。

例子:

    file_handler = open(fname, 'r')
    for line in file_handler:
       if line[0] == '#':
           print line
       else:
           line2 = file_handler.readline()
           print line2

基本上在这个例子中我试图逐行阅读它,但是当该行不是以#我想阅读下一行时,打印它,然后继续阅读第 2 行之后的行。这只是一个示例,我在代码中遇到了类似的错误,但我的目标如标题中所述。

但我会得到一个像ValueError: Mixing iteration and read methods would lose data.

是否有可能以更聪明的方式做我想做的事情?

4

6 回答 6

6

如果您只想跳过不以 开头的行#,有一种更简单的方法可以做到这一点:

file_handler = open(fname, 'r')
    for line in file_handler:
       if line[0] != '#':
           continue
       # now do the regular logic
       print line

显然,这种简单化的逻辑并不适用于所有可能的情况。如果没有,您必须完全按照错误的含义进行操作:要么一致地使用迭代,要么一致地使用读取方法。这将变得更加乏味且容易出错,但并没有那么糟糕。

例如,使用readline

while True:
    line = file_handler.readline()
    if not line:
        break
    if line[0] == '#':
        print line
    else:
        line2 = file_handler.readline()
        print line2

或者,通过迭代:

lines = file_handler
for line in file_handler:
    if line[0] == '#':
        print line
    else:
        print line
        print next(file_handler)

然而,最后一个版本有点“作弊”。您依赖于for循环中的迭代器与创建它的可迭代对象相同的事实。这恰好适用于文件,但不适用于列表。所以真的,你应该在这里做同样的while True循环,除非你想添加一个明确的iter调用(或者至少一个解释你为什么不需要的注释)。

更好的解决方案可能是编写一个生成器函数,根据您的规则将一个迭代器转换为另一个迭代器,然后打印出该生成器迭代的每个值:

def doublifier(iterable):
    it = iter(iterable)
    while True:
        line = next(it)
        if line.startswith('#'):
            yield line, next(it)
        else:
            yield (line,)
于 2013-04-29T22:18:09.800 回答
1
file_handler = open(fname, 'r')
for line in file_handler:
   if line.startswith('#'): # <<< comment 1
       print line
   else:
       line2 = next(file_handler) # <<< comment 2
       print line2

讨论

  1. 您的代码使用了一个等号,这是不正确的。它应该是双等号进行比较。我建议使用 .startswith() 函数来提高代码清晰度。

  2. next()由于您使用file_handler的是迭代器,因此请使用该函数前进到下一行。

于 2013-04-29T22:25:10.360 回答
0

添加标志值:

if flag is True:
    print line #or whatever
    flag = False
if line[0] == '#':
    flag = True

这是多功能版本:-)

于 2013-04-29T22:19:15.603 回答
0

您可以保存一些状态信息,告诉您如何处理下一行:

want_next = False
for line in open(fname):
    if want_next:
        print line
        want_next = False
    elif line[0] == '#':
        print line
        want_next = True
于 2013-04-29T22:29:55.860 回答
0

我认为您正在寻找的是next而不是readline. 一些东西。在您的代码中,您使用 = 而不是 ==。我将改用startswith。如果在迭代器上调用 next,它将返回下一项或抛出 StopIteration 异常。

文件

ewolf@~ $cat foo.txt
# zork zap
# woo hoo
here is 
some line
# a line
with no haiku

该程序

file_handler = open( 'foo.txt', 'r' )
for line in file_handler:
    line = line.strip()
    if line.startswith( '#' ):
        print "Not Skipped : " + line
    elif line is not None:
    try:
        l2 = file_handler.next()
            l2 = l2.strip()
            print "Skipping. Next line is  : " + l2
        except StopIteration:
            # End of File                                                       
            pass

输出

Not Skipped : # zork zap
Not Skipped : # woo hoo
Skipping. Next line is  : some line
Not Skipped : # a line
Skipping. Next line is  : 
于 2013-04-29T22:34:49.710 回答
-2

尝试if line[0] == "#"代替 line[0] = "#"

于 2013-04-29T22:21:57.317 回答