Python 使用列表理解返回第一个找到的元素或无

Python 使用列表理解返回第一个找到的元素或无,python,list-comprehension,Python,List Comprehension,我想优化我的python代码,我认为我可以通过列表理解来改进以下for循环,以提高性能: for obj in self.objs: if obj.is_runnable(): return obj return None 我的想法是这样做: objs = [obj for obj in self.objs if obj.is_runnable()] return objs[0] 但我认为这不会更好,因为它不会在第一个找到的元素之后停止迭代,现在它不会处理None的情

我想优化我的python代码,我认为我可以通过列表理解来改进以下for循环,以提高性能:

for obj in self.objs:
    if obj.is_runnable():
        return obj
return None
我的想法是这样做:

objs = [obj for obj in self.objs if obj.is_runnable()]
return objs[0]
但我认为这不会更好,因为它不会在第一个找到的元素之后停止迭代,现在它不会处理
None
的情况,但这可以通过
if-else
语句避免。
我的问题:有没有一种方法可以使用列表理解,它在返回第一个元素后会中断?

使用默认值:

return next((obj for obj in self.objs if obj.is_runnable()), None)
请注意,我将列表理解
[…]
更改为生成器表达式
(…)
,否则在获取第一个元素之前仍将创建整个列表。使用
(…)
,它只会根据需要测试尽可能多的元素

或者使用
filter
,其中
ClassOfObj
obj
类的占位符:

return next(filter(ClassOfObj.is_runnable, self.objs), None)

您应该看看这个答案:-TLDR,列表理解可能不会比循环首先没有创建或附加到列表的循环快。还要注意,您当前的实现是正确的惯用实现-它正确、清晰、简单、明显,并且非常容易跟踪。提示1:不要尝试变得聪明,提示2:不要尝试优化未经验证(使用探查器)存在性能问题的代码(注意:我不是说“编写愚蠢和低效的代码”,只是“尽可能简单和明显”),提示3:真正的优化通常需要使用另一种数据结构和算法(和/或在Python用C重写关键部分的情况下,或使用已经提供一种或两种策略的库)@Brunodesshuilliers我想到了这一点,但感谢你的澄清。我知道,代码片段花了很长时间,我不知道
is_runnable
方法是花了很长时间还是for循环。事实上,这是'is_runnable'调用,因为我访问pandas数据帧行的速度很慢,但我认为,generator expressio是有原因的ns和列表理解,那么为什么不使用它呢?@RoQuOTriX profiling会告诉您问题所在。是的,生成器表达式等有很好的理由,但您的案例肯定不是这些理由的一部分(IMHO等)。“为什么不使用它?”?很简单,因为您接受的答案中的解决方案远没有您最初的实现那么简单、明显、可读性和可维护性。您已经在这里(20多年的经验),做到了这一点(尝试通过使用所有的铃铛和口哨来做个聪明人),最后。但是YMMV当然;-)wrt/generator表达式(以及其他懒惰的可重用性),重点主要是懒惰的计算(避免无用的计算和内存使用).现在没有人会因为使用tobias的解决方案而杀了你-但是一个初级开发人员很难理解它,即使是一个经验丰富的python程序员也需要比你的初始版本多一点的时间来获得它-也许是一瞬间,但是当试图调试一个嵌套很深的问题时,即使是一瞬间无用的分心也是一个PITA。你怎么办你是说占位符?类名?我不能用过滤器运行它approach@RoQuOTriX您必须将对该方法的引用传递给
filter
。因为它是该对象的一个方法,所以您必须以
ClassName.method
的形式传递它。但是您也可以使用第一个版本。这是
下一个
方法吗有一个名字我可以像列表理解一样搜索吗?@RoQuOTriX
next
是一个内置函数(参见提供的链接),与
[…]相反的
(…)
被称为生成器表达式。我得到了错误:模块“ObjClass”没有属性“is_runable”。我做错了什么?