列表推导式返回“生成器对象...”

6
我将尝试从字典中简洁地创建一个列表。
以下代码可行:
def main():
    newsapi = NewsApiClient(api_key=API_KEY)
    top_headlines = newsapi.get_everything(q="Merkel",language="en")
    news = json.dumps(top_headlines)
    news = json.loads(news)
    articles = []
    for i in news['articles']:
        articles.append(i['title'])
    print(articles)

输出:

['Merkel “Helix Suppressor” Rifle and Merkel Suppressors', 'Angela Merkel', 
 'Merkel says Europe should do more to stop Syria war - Reuters', 
 'Merkel says Europe should do more to stop Syria war - Reuters', 
 'Merkel muss weg! Merkel has to go! Demonstrations in Hamburg', ... , 
 "Bruised 'Queen' Merkel Lives..."]

但我在其他地方看到了列表推导式,并一直在尝试学习。用以下列表推导式替换for i in news['articles']:

def main():
    ...
    articles = []
    articles.append(i['title'] for i in news['articles'])
    print(articles)

我本以为会得到类似的输出,但实际返回了:
[<generator object main.<locals>.<genexpr> at 0x035F9570>]

我找到了这个相关的解决方案,但是执行以下操作会输出标题(好耶!)三次(不好!):
def main():
    ...
    articles = []
    articles.append([i['title'] for x in news for i in news['articles']])
    print(articles)

通过列表推导式生成文章的正确方式是什么?

忽略我在main()中有例程而不是函数调用的事实。我稍后会修复它。


2
列表推导式创建一个列表。如果你将该列表附加到你的列表中,你得不到想要的输出。不要附加,只需将推导式的结果分配给你的变量即可。 - Aran-Fey
(i['title'] for i in news['articles']) 是一个生成器表达式。您是否意图将其传递给 extend 而非 append - zvone
@Aran-Fey - 哦!!那就很有道理了。这个做法是有效的:articles = [i['title'] for i in news['articles']] :D - BruceWayne
3个回答

6

只需使用:

articles = [i['title'] for i in news['article']]

列表推导式已经返回一个列表,因此无需创建空列表并将值附加到其中。想要了解有关列表推导式的指南,您可以查看这个链接
关于生成器对象,问题在于在括号()之间使用列表推导式(或者说没有用括号包含它们)会创建一个生成器而不是一个列表。要了解有关生成器与列表的区别,请参见Generator Expressions vs. List Comprehension,有关生成器推导式的信息,请参见How exactly does a generator comprehension work?

我怎样才能区分生成器和列表推导式?它们看起来非常相似。(当然,我也会在谷歌上搜索,只是想知道是否有快速的方法) - BruceWayne
3
列表推导式用 [ ] 括起来,与字典推导式用 { } 相似。 - MooingRawr
3
列表推导式用括号包围(就像列表字面值一样)。生成器表达式使用圆括号,如果生成器是函数调用的单个参数,则可以省略括号(例如在articles.append(i['title'] for i in news['articles'])中)。 - Aran-Fey
@xg.plt.py - 或许这可以帮助你。在Matt_G的回答中,我不明白为什么第一个是生成器。它被[]包围,这让我认为它应该是列表推导式,而不是生成器(不考虑他使用了.append())。 - BruceWayne
@BruceWayne 它生成一个列表。如果它是一个生成器,你会得到将一个生成器附加到列表中而不是它的值。这种情况是在“生成器表达式 vs. 列表推导”问题中所解释的。 - OriolAbril
显示剩余3条评论

3

替换:

articles.append(i['title'] for i in news['articles'])

使用:

articles+=[i['title'] for i in news['articles']]

0

在你所处的上下文中使用它会生成一个生成器:

 articles.append(i['title'] for x in news for i in news['articles'])

像这样使用会产生一个列表:

articles = [i['title'] for i in news['articles']]

1
第一个表达式也会生成一个列表,而不是生成器。否则,值将不会被附加到articles中,而是留下长度为1的列表。 - OriolAbril
抱歉,我复制了他代码的错误行。已进行编辑以反映正确的行。 - Matt_G
在第一个例子中,我是否正确地认为我的“articles”列表正在附加生成器?我之后可以继续向该列表添加字符串吗?或者说你不能在列表中混合使用生成器和字符串类型? - BruceWayne
2
@BruceWayne,你可以毫不费力地混合使用字符串和生成器。在Python中,列表可以包含任何类型的对象,并且可以混合使用,每个位置可以包含不同的对象。 - OriolAbril

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接