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

tim*_*lly 62 python list-comprehension

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

actor = [actor for actor in self.actors if actor.name==actorName][0]
Run Code Online (Sandbox Code Playgroud)

(self.actors包含一个对象列表,我试图找到一个具有特定(字符串)名称的名称,该名称位于actorName中.)

我正在尝试从列表中提取与我正在寻找的参数匹配的对象.这种方法不合理吗?晃来晃去[0]让我觉得有点不安全.

zee*_*kay 96

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

actor = next(actor for actor in self.actors if actor.name==actorName)
Run Code Online (Sandbox Code Playgroud)

正如发送者指出的那样,这种方法的另一个优点是,如果找不到匹配项,您可以指定默认值:

actor = next((actor for actor in self.actors if actor.name==actorName), None)
Run Code Online (Sandbox Code Playgroud)

  • 效率更高 - 如果找不到匹配项,则允许您指定默认值. (8认同)

Ben*_*kin 20

如果你想参加可能很多的第一场比赛,那就next(...)太棒了.但是如果你只想到一个,那就考虑一下防守:

[actor] = [actor for actor in self.actors if actor.name==actorName]
Run Code Online (Sandbox Code Playgroud)

这总是扫描到最后,但不像[0],[actor]如果存在0或多个匹配,则解构为抛出ValueError.也许更重要的是捕捉错误,这将您的假设传达给读者.

如果你想要0匹配的默认值,但仍然捕获> 1匹配:

[actor] = [actor for actor in self.actors if actor.name==actorName] or [default]
Run Code Online (Sandbox Code Playgroud)

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

[actor] = (actor for actor in self.actors if actor.name==actorName)
Run Code Online (Sandbox Code Playgroud)

哪个应该更有效率.您可以在左侧使用元组语法 - 看起来更加对称,但逗号很难看,也很容易错过恕我直言:

(actor,) = (actor for actor in self.actors if actor.name==actorName)
actor, = (actor for actor in self.actors if actor.name==actorName)
Run Code Online (Sandbox Code Playgroud)