我有一个列表,我想通过项目的属性进行筛选。
以下哪个是首选(可读性,性能,其他原因)?
xs = [x for x in xs if x.attribute == value]
xs = filter(lambda x: x.attribute == value, xs)
我有一个列表,我想通过项目的属性进行筛选。
以下哪个是首选(可读性,性能,其他原因)?
xs = [x for x in xs if x.attribute == value]
xs = filter(lambda x: x.attribute == value, xs)
当前回答
你的问题既简单又有趣。它只是显示了python作为一种编程语言是多么的灵活。人们可以使用任何逻辑,根据自己的才能和理解来编写程序。只要我们得到答案就好。
在您的情况下,这只是一个简单的过滤方法,可以由两者完成,但我更喜欢第一个my_list = [x for x in my_list if x.attribute == value],因为它看起来简单,不需要任何特殊的语法。任何人都可以理解这个命令,并在需要时进行更改。 (虽然第二种方法也很简单,但对于初级程序员来说,它仍然比第一种方法更复杂)
其他回答
一般过滤器稍快,如果使用内置函数。
在您的情况下,我希望列表理解稍微快一些
就性能而言,这要视情况而定。
filter不返回一个列表而是一个迭代器,如果你需要列表“立即”过滤和列表转换,它比非常大的列表(>1M)的列表理解要慢40%左右。到100K的元素几乎没有区别,从600K开始就开始有区别了。
如果不转换为列表,筛选实际上是即时的。
更多信息请访问:https://blog.finxter.com/python-lists-filter-vs-list-comprehension-which-is-faster/
我会得出结论:使用列表理解而不是过滤器,因为它
更具可读性 更多的神谕的 更快(对于Python 3.11,参见附带的基准测试,也参见)
请记住,filter返回一个迭代器,而不是一个列表。
python3 -m timeit '[x for x in range(10000000) if x % 2 == 0]'
1个循环,5个最佳:每循环270毫秒
python3 -m timeit 'list(filter(lambda x: x % 2 == 0, range(10000000)))'
1个循环,最好的5:432毫秒每循环
奇怪的是,在Python 3上,我看到过滤器执行得比列表推导更快。
我一直认为列表推导式的性能会更好。 喜欢的东西: [name为brand_names_db中的name,如果name不是None] 生成的字节码稍好一些。
>>> def f1(seq):
... return list(filter(None, seq))
>>> def f2(seq):
... return [i for i in seq if i is not None]
>>> disassemble(f1.__code__)
2 0 LOAD_GLOBAL 0 (list)
2 LOAD_GLOBAL 1 (filter)
4 LOAD_CONST 0 (None)
6 LOAD_FAST 0 (seq)
8 CALL_FUNCTION 2
10 CALL_FUNCTION 1
12 RETURN_VALUE
>>> disassemble(f2.__code__)
2 0 LOAD_CONST 1 (<code object <listcomp> at 0x10cfcaa50, file "<stdin>", line 2>)
2 LOAD_CONST 2 ('f2.<locals>.<listcomp>')
4 MAKE_FUNCTION 0
6 LOAD_FAST 0 (seq)
8 GET_ITER
10 CALL_FUNCTION 1
12 RETURN_VALUE
但它们实际上更慢:
>>> timeit(stmt="f1(range(1000))", setup="from __main__ import f1,f2")
21.177661532000116
>>> timeit(stmt="f2(range(1000))", setup="from __main__ import f1,f2")
42.233950221000214
尽管过滤器可能是“更快的方式”,但“Python方式”是不关心这些事情,除非性能绝对关键(在这种情况下,您不会使用Python!)。