在列表解析中迭代列表的一部分

时间:2014-06-15 18:24:22

标签: python python-2.7 file-io list-comprehension

我想打印出文件的前10行,避免读取任何额外的行。如何在不读取整个文件的情况下使用列表推导来做到这一点?

我知道我可以这样做代码:

N = 10
with open(path,'rb') as f_in:
    for line in f_in:
        print line.strip()
        N -= 1
        if N == 0:
            break

但我认为列表理解更合适:

with open(path,'rb') as f_in:
    [print line for i, line in enumerate(f_in) if i<N]

然而,由于打印声明,这不起作用,所以我最终得到了这个烂摊子:

with open(path,'rb') as f_in:
    lines = [line.strip() for i, line in enumerate(f_in) if i<N]
    for line in lines:
        print line

我的问题的真正意义在于,当我= = N而不是不必要地继续并且只过滤掉额外的行时,你如何让列表理解停止?

有没有办法限制列表理解将进入迭代器的距离?是否有适当的方式从列表理解中打印出来?我对python很新,所以我试图学习如何以正确的方式做事,而不仅仅是我能想到的第一种方式。我想以pythonic的方式写这个。

2 个答案:

答案 0 :(得分:3)

  

当i == N而不是时,你如何让列表理解停止?   不必要的继续,只过滤掉额外的线?   有没有办法限制列表理解将进入迭代器的距离?

您可以使用itertools.islice迭代一个可迭代的片段:

from itertools import islice

with open(path,'rb') as f_in:
    for line in islice(f_in, N):
        print line.strip()

实际上,您可以指定要生成的第一行的索引,甚至是步骤(如列表或字符串切片)。

请注意,如果您实际上不需要列表,则不应使用list-comprehension,因为它会消耗内存(在您的情况下,您将文件的所有内容保留在内存中,如果文件中的文件内容可能会很糟糕很大)。 如果你只想迭代一次使用生成器表达式:

lines = (line.strip() for line in f_in)

(是的,您只需使用[]更改())。 这避免了在执行时构建整个列表。

  

是否有合适的方法从列表理解中打印出来?

没有

在python2中print是一个语句,因此它不能出现在表达式中 在python3中你可以调用print,因为它是一个函数,但它是非常糟糕的主意

列表推导有一个特定的目的:从给定的可迭代构建列表。 你扔掉了这个列表,从而打败了那个语法的整个目的。

由于这个原因,在列表理解中不支持“打破”循环。如果您的代码非常复杂,需要break,那么最好使用明确的for循环编写代码。

如果您尝试执行调用map

之类的操作,情况也是如此
map(lambda line: print line, lines)

假设可以在print

中插入lambda

这甚至在python3中失败(它不会打印任何东西)。

如果你想编写好的python代码,首要的规则是遵循语言设计: 不要混合表达式和语句,也就是说:使用表达式返回值,不要滥用它们来产生副作用。

答案 1 :(得分:1)

您还可以在所需的行范围内调用文件对象上的next()

lines = [f_in.next() for x in range(10)]

这将为您提供前十行。

如果要在文件开头跳过标题或其他行,则使用next()会很有用。每次在文件对象上调用next时,都将移动到文件的下一行。

如果您想打印行的内容,可以使用join()

print "".join(lines)