生成器表达式在管道中使用时未按预期工作

0 投票
2 回答
47 浏览
提问于 2025-04-14 15:58

我正在尝试使用生成器表达式,以便更好地理解它们。我有一个文本文件,我原本希望以下代码能把文件中每一行的每个单词单独打印出来:

lines = open("file.txt")
split_lines = (line.split() for line in lines)
words = (word for word in split_lines)
for word in words:
    print(word)

我找到的一个解决办法是放弃使用单词生成器表达式,而是用一个嵌套循环来遍历创建的列表:

lines = open("file.txt")
split_lines = (line.split() for line in lines)
for split_line in split_lines:
    for word in split_line:
        print(word)

但我仍然在想,我的理解中到底有什么缺口,以至于我看不出为什么第一种方法不奏效(感觉单词生成器表达式实际上没有做什么,只是让我保留了之前的那个列表)。

2 个回答

2

这个 split_line 生成器会返回每一行通过 line.split() 处理后的结果。返回的是一个个单词的列表,而不是单个的单词。比如:

lines = ["a b c", "d e f"]
>>> split_lines = (line.split() for line in lines)
>>> list(split_lines)
[['a', 'b', 'c'], ['d', 'e', 'f']]
>>> 

如果你想把这些列表“扁平化”,也就是说让你的 words 生成器返回单个的单词,而不是单词的列表,你可以这样做:

>>> split_lines = (line.split() for line in lines)
>>> words = (word for line in split_lines for word in line)
>>> list(words)
['a', 'b', 'c', 'd', 'e', 'f']
>>> 

所以你最开始的例子看起来会是这样的:

lines = open("file.txt")
split_lines = (line.split() for line in lines)
words = (word for line in split_lines for word in line)
for word in words:
    print(word)

你也可以把生成器合并,这样就不需要 split_lines 了:

lines = open("file.txt")
words = (word for line in lines for word in line.split())
for word in words:
    print(word)
1

这和生成器没有关系。比如,如果你把(换成[来创建列表:

>>> split_lines = [line.split() for line in open('file.txt')]
>>> words = [word for word in split_lines]
>>> words
[['Thu', 'Mar', '14', '16:45:57', '-03', '2024'], ['Thu', 'Mar', '14', '16:46:00', '-03', '2024'], ['Thu', 'Mar', '14', '16:46:01', '-03', '2024'], ['Thu', 'Mar', '14', '16:46:02', '-03', '2024'], ['Thu', 'Mar', '14', '16:46:02', '-03', '2024'], ['Thu', 'Mar', '14', '16:46:02', '-03', '2024']]

你会发现问题在于你的第二个表达式只是遍历第一个表达式,并且返回它收到的内容。

在这种情况下,你想要的是遍历里面的元素,而不是元素本身。你可以用words = (word for line in split_lines for word in line)来实现这个功能(或者用list,思路是一样的)。

撰写回答