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

我开始习惯于在Python中列出理解,但恐怕我有点不正确的使用它。 我遇到了几次使用列表理解的场景,但立即从生成的列表中获取第一个(也是唯一的)项目。 这里是一个例子:

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

(self.actors包含一个对象的列表,我试图find一个特定的(string)名称,这是在actorName。)

我试图从列表中提取匹配我正在寻找的参数的对象。 这种方法不合理吗? 悬空[0]让我觉得有点不安全。

你可以用一个生成器expression式来代替。 这也会更有效率,因为没有创build中间列表,并且一旦find匹配就可以停止迭代:

 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) 

如果你想参加第一场比赛, next(...)是很棒的。 但是,如果你期望得到一个,可以考虑防御性地写:

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

这总是扫描到最后,但不像[0] ,如果有0个或多个匹配,解构成[actor]将抛出一个ValueError。 或许更重要的是捕捉错误,这将你的假设传达给读者。

如果你想要一个默认值为0的匹配,但仍然赶上> 1匹配:

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

PS也可以在右侧使用生成器expression式:

 [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] 

就我个人而言,我会在适当的循环。

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

这是相当长的时间,但它确实有一个优点,即一旦find匹配就停止循环。

这篇文章有一个自定义的find()函数,效果很好,并且有一个评论者也链接到了基于生成器的这个方法 。 基本上,这听起来像没有一个伟大的方式来做到这一点 – 但这些解决scheme并不坏。