如果只有一个结果,可以替代列表理解


74

我开始习惯于在Python中列出理解,但恐怕我使用不当。我遇到了几次使用列表推导但立即从生成的列表中获取第一个(也是唯一一个)项目的情况。这是一个例子:

actor = [actor for actor in self.actors if actor.name==actorName][0]

(self.actors包含一个对象列表,我正在尝试使用具有特定(字符串)名称的对象,该名称在actorName中。)

我试图从与我要寻找的参数匹配的列表中拉出对象。这种方法不合理吗?悬吊的[0]使我感到有点不安全。


2
不要害怕,这不是那么糟糕:)找到匹配项后停止循环的以下答案之一可能是一个更好的选择。next(<generator_exp>)还算不错,但是如果您尝试使其在80个字符的行中工作,则可能会变得很难看。如果您要按名称查找一群演员,那么制作一个更好的主意会更好,dict因此您可以直接查找它们。
John La Rooy

幸运的是,这不是我经常或大范围地做的事情。我对字典相当满意,并且会牢记该技巧。
timfreilly 2011年

Answers:


116

您可以使用生成器表达式next来代替。这也将更加有效,因为不会创建中间列表,并且一旦找到匹配项,迭代就会停止:

actor = next(actor for actor in self.actors if actor.name==actorName)

正如senderle指出的那样,此方法的另一个优点是,如果找不到匹配项,则可以指定默认值:

actor = next((actor for actor in self.actors if actor.name==actorName), None)

9
效率更高-如果找不到匹配项,则允许您指定默认值。
senderle'8

谢谢。您能否澄清“不需要食用”?这是否意味着一旦找到匹配项,它将停止迭代?
timfreilly,2011年

在这方面澄清了措词。
2011年

谢谢。这绝对是有用的信息,并且明显优于我的方法。
timfreilly,2011年

这些单行代码越来越热爱Python!:]
Kostas Demiris

25

如果您想参加可能很多的第一场比赛,那就next(...)太好了。但是,如果您期望得到一个,请考虑防御性地编写:

[actor] = [actor for actor in self.actors if actor.name==actorName]

这始终扫描到最后,但不同[0]解构赋值[actor]如果存在0个或多个匹配项引发ValueError。也许比发现错误更重要,这会将您的假设传达给读者。

如果您想要默认的0个匹配项,但仍捕获> 1个匹配项:

[actor] = [actor for actor in self.actors if actor.name==actorName] or [default]

PS,也可以在右侧使用生成器表达式:

[actor] = (actor for actor in self.actors if actor.name==actorName)

这可能会更有效(?)。您也可以在左侧使用元组语法-看起来更对称,但逗号很难看,而且容易错过恕我直言:

(actor,) = (actor for actor in self.actors if actor.name==actorName)
actor, = (actor for actor in self.actors if actor.name==actorName)

(无论如何,列表和元组语法在左侧纯粹是装饰性的,不影响行为)


1
您可能已经看到了:[a, b] = [b, a]用于交换,尽管通常不带括号显示。这称为“解构任务”或“拆箱”。左侧的方括号/父项是可选的,但对于单元素情况是必需的。右侧可以是任何python表达式,在这种情况下为列表理解。
贝尼·切尔尼亚夫斯基-帕斯金

我懂了。感谢您的术语。我在其他情况下使用打包/拆包,但从未将其与单个变量一起使用来强制单个结果。
timfreilly 2011年

2

这篇文章有一个自定义find()功能,效果很好,并且其中的评论者也基于generators链接到此方法。基本上,似乎没有单一的好方法可以做到这一点-但这些解决方案也不错。


有趣的是,有关于此主题的博客文章。感谢您的概述,我很难找到有关此问题的信息。
timfreilly,2011年

1

我个人希望在适当的循环中进行此操作。

actor = None
for actor in self.actors:
    if actor.name == actorName:
        break

它更长了一点,但是确实具有一个优势,一旦找到匹配项,它就会停止循环。


4
next()解决方案一样。
glglgl 2011年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.