List comprehension without 'for'
通常,在使用Python中的列表时,我最终只希望从列表中筛选出项目。
1 2
| numbers = [5, 1, 4, 2, 7, 4]
big_nums = [num for num in numbers if num > 2] |
对我来说,这似乎是不必要的冗长。我必须在两个单独的语句(num for num ...中定义和使用num,即使我没有对num执行任何操作。
我试过[num in numbers if num > 2],但python用这个扔了一个SyntaxError。
在python中是否有更简洁的方法可以做到这一点?
编辑:
我的问题是,是否有更好的方法来完成我在Python中所做的工作。有很多次,我不知道在Python中有一个构造,但这使我的代码更好,更可读。
我不想问关于filter和列表理解之间的性能权衡。我对列表理解没有问题,但是在我了解列表理解之前,我也对使用标准的for循环构建列表没有问题。
- 这似乎是一个代码高尔夫问题,而不是一个实际的问题,python代码是为了可读。
- [num in numbers if num > 2]使您看起来像是在使用包含in表达式的三元表达式(x if y else z,而您只是忘记了else子句。
- 我看不出那个清单理解有什么问题。
- 注意:受骗者会回答你的问题以及更多。一个简单的"列表理解替代"谷歌搜索会把它作为第一个结果。
- fwiw,如果numbers是一个1d numpy数组,你可以做numbers[numbers>2]
- @ C????S?????口供内容丰富,但不能回答我的问题。我猜我的问题答案是"不",但我的问题和建议的重复不一样(见我的编辑)
- "应该有一种——最好只有一种——显而易见的方法来做到这一点。尽管一开始这种方式可能并不明显,除非你是荷兰语。
- @PM2很好,所以这个问题是针对我们这些非荷兰语的人的,需要一些帮助。
- 够公平的。:)原则"一个明显的方法"不像以前那样严格(例如,我们现在有几种方法来格式化字符串),但一般来说,如果有明显的方法,那么使用它可能比搜索模糊的替代方法更好,因为显而易见的方法可能更容易理解和更易读。奥思,"实用胜过纯洁"…
好吧,你可以使用filter,它比较慢,也不可读,但是你不需要for:
1
| list(filter(lambda x: x > 2, numbers)) |
或:
1
| list(filter((2).__lt__, numbers)) |
然而,使用这种神奇的方法是脆弱的,只有当列表只包含整数时,这种方法才有效。正如Chris_Rands指出的,你通常使用operator.lt代替:
1 2 3
| from functools import partial
from operator import lt
list(filter(partial(lt, 2), numbers)) |
如果列表中包含除int以外的其他数字类型,这也会起作用。
- 很好地使用了__lt__!+ 1
- 可能更快,因为没有lambda
- 可能从运营商进口lt会更"Python"?
- 吉恩·弗朗索瓦说的话。另外,您可以使用splat解包,而不是调用list构造函数:[*filter((2).__lt__, numbers)]。但我同意标准的列表合成方式更好,即使重复有点烦人。
- @Chris_Rands也许,因为直接调用Dunder方法通常是不受欢迎的;Otoh,有时直接调用Dunder方法是有意义的,imho这就是其中之一。但是,当然,仅仅使用标准的list-comp语法就更像是Python了,而这正是OP所抱怨的。;)