将函数应用于循环项

时间:2014-12-31 22:21:36

标签: python loops iteration

请考虑以下代码:

f = open('file.txt')

for l in f:
    k = l.strip() # Remove the newline character.
    print(k)

f.close()

我想自动删除换行符。我知道我能做到:

for k in [l.strip() for l in f]:
    print(k)

但这需要将f的长度循环两次(并将整个内容加载到内存中)。我想知道是否还有像Pythonic这样的东西:

for lambda l: l.strip() in f:
    print(l)

或者只是:

for l.strip() in f:
    print(l)

当然,这些都不起作用。要了解如何将其应用于其他地方,以下是嵌套列表的示例:

d =  [['hi'], ['hello'], ['howdy']]
for item in d:
    item = item[0] # Get the nested item.
    if item == 'hello':
         print(item)

3 个答案:

答案 0 :(得分:5)

您可以使用generator expression

for k in (l.strip() for l in f):
    print(k)

这与列表理解非常相似,不同之处在于它会懒惰地(逐个)生成项目,而不是一次性将它们全部收集到列表中。因此,我们一次只循环f的长度,同时避免将所有内容全部转储到内存中。

答案 1 :(得分:3)

欢迎来到Python迭代器的世界:)

你对列表推导有正确的想法,除了你想要它延迟加载而不是首先在内存中建立整个列表(对于非常大的文件甚至可能是站不住脚的):使用生成器表达式< / strong>相反,它具有相同的语法,除了方括号被括号替换(如果它是函数的唯一参数,则可省略):

with open(filename) as f:
    for l in (l.strip() for l in f.readlines()):
        print(l)
  

来源:the relevant Python Enhancement Proposalofficial docs了解更多相关信息。


使用类似于LISP的语法来实现它的另一种功能方法是使用map将函数应用于迭代器的每个元素 - 它不必是序列并假设您使用Python,这将涉及仅循环遍历所有行:

for l in map(lambda l: l.strip (), f):
    print(l)

另外,f.readlines()可能比仅仅循环f更清晰,with语句比自己调用f.close()更加Pythonic。

答案 2 :(得分:0)

尚未测试但应该是正确的:重要的部分是使用replace。在我看来,for循环是一种有效的方法,但是如果你想要一个衬里,请使用类似的东西:

no_new_lines = None
with open('path/to/file', 'rb') as file_content:
    no_new_lines = file_content.read().replace('\r\n', '\n').replace('\n', '')

请注意“replace”会复制要替换的内容。在内存很少的系统上打开一个巨大的文件会导致问题(MemoryError)。无论如何,测试它,看看哪个更好。