[英]python3 itertools.filterfalse is very slow. What are the alternatives?
[英]Are there any efficiency benefits to using `itertools.filterfalse()` as opposed to `filter(not function, iter)`?
標題說明了一切,差不多。 如果我想使用filter
function 在range(10)
中查找所有大於 5 的數字,我可以這樣做:
result = filter(lambda x: x>5, range(10))
但是, itertools
模塊有filterfalse
function,據我所知,基本上可以
result = filter(lambda x: not x>5, range(10))
我錯了嗎? 擁有這樣的 function 有什么好處嗎? 與傳統切片相比,其他函數(如islice
有一些小的優勢,所以我認為filterfalse
也會有一個小眾用途。
我認為 itertools 模塊主要提供便利功能。 它們允許您快速編寫(高效)代碼。 例如,假設您有一些 function 來測試某個屬性,例如測試 object 是否是超過 3 個字符的字符串:
def is_long_string(x):
return isinstance(x, str) and len(x) > 3
現在,如果您想從對象列表中過濾所有此類字符串,您可以編寫:
input_objects = [1, 2, 3.14, 'foo', 'bar', 'qux', 'xyzzy']
long_strings = list(filter(is_long_string, input_objects))
但是,如果您想擁有所有其他對象,則必須編寫is_not_long_string()
function,或使用 lambda ZC1C425268E68385D1AB5074C17A9:F4
not_long_strings = list(filter(lambda x: not is_long_string(x), input_objects))
使用 itertools 您可以更輕松地編寫:
not_long_strings = list(itertools.filterfalse(is_long_string, input_objects))
filterfalse()
function 只是提供了內置filter()
function 的“反向”操作,即 ZA7F5F35426B927411FC9231B5638271 語言本身缺少的東西。
是否要使用第一種或第二種形式(lambda 或 itertools)是個人喜好問題。
在您的示例中,您已經在使用 lambda function,因此在這種情況下使用 itertools 不會提供更多的可讀性或便利性。
注意:就像 Andrej 在他的回答中已經證明的那樣,性能不是使用 itertools 的主要原因(重寫謂詞 function 可能會帶來更好的性能)。
timeit
模塊的快速基准測試表明,使用filter()
和itertools.filterfalse()
具有大致相同的性能。 列表理解肯定更快:
from timeit import timeit
from itertools import filterfalse
N = 10_000
def f1():
return list(filter(lambda x: x>5, range(N)))
def f2():
return list(filterfalse(lambda x: not x>5, range(N)))
def f3():
return [i for i in range(N) if i > 5]
t1 = timeit(lambda: f1(), number=10)
t2 = timeit(lambda: f2(), number=10)
t3 = timeit(lambda: f3(), number=10)
print(t1)
print(t2)
print(t3)
在我的電腦上打印(AMD 2400G、Python 3.8):
0.018814088001818163
0.01380085300115752
0.007684074000280816
編輯: not
從filterfalse()
中刪除:
from timeit import timeit
from itertools import filterfalse
N = 10_000
def f1():
return list(filter(lambda x: x>5, range(N)))
def f2():
return list(filterfalse(lambda x: x<=5, range(N)))
def f3():
return [i for i in range(N) if i > 5]
t1 = timeit(lambda: f1(), number=10)
t2 = timeit(lambda: f2(), number=10)
t3 = timeit(lambda: f3(), number=10)
print(t1)
print(t2)
print(t3)
印刷:
0.01010196800052654
0.01007204300549347
0.005998152002575807
編輯:使用 Perfplot 進行基准測試:
import perfplot
from itertools import filterfalse
def f1_filter(r):
return list(filter(lambda x: x>5, r))
def f2_filterfalse(r):
return list(filterfalse(lambda x: x<=5, r))
def f3_comprehension(r):
return [i for i in r if i > 5]
def setup(n):
return range(n)
perfplot.show(
setup=setup,
kernels=[f1_filter, f2_filterfalse, f3_comprehension],
labels=['filter', 'filterfalse', 'comprehension'],
n_range=[10**i for i in range(1, 7)],
xlabel='N',
logx=True,
logy=True)
顯示:
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.