itertools
モジュールに慣れようとしていますが、ifilter
という関数を見つけました。
私の理解では、指定された関数に基づいてフィルター処理と反復可能を行い、関数がTrue
と評価する反復可能要素の要素を含むリストに対して反復子を返します。
質問1:これまでの私の理解は正しいですか?
質問2:これが戻り、イテレータであるという事実を除けば、組み込みのfilter
関数とどう違うのですか?
質問どちらが速いですか?
私の知る限りではありません。私は何かが足りないのですか? (私は次のテストを実行しました)
>>> itertools.ifilter(lambda x: x%2, range(5))
<itertools.ifilter object at 0x7fb1a101b210>
>>> for i in itertools.ifilter(lambda x: x%2, range(5)): print i
...
1
3
>>> filter(lambda x: x%2, range(5))
[1, 3]
>>> function = lambda x: x%2
>>> [item for item in range(5) if function(item)]
[1,3]
以下の例には、数値を生成する直前にメッセージを出力し、filter()
が最初にリストを作成し、次にそれを実行してフィルタリングする方法を示す数値ジェネレーターが含まれています。一方、itertools.ifilter
フィルターをかけながら、リストを作成することはありません。 500,000の重要なものをフィルタリングする場合は、ifilter
が必要なので、リストを作成する必要はありません。
import itertools
def number_generator():
for i in range(0, 3):
print "yield", i
yield i
print "stopping"
function = lambda x: x > 0
numbers = number_generator()
print "itertools.ifilter:"
for n in itertools.ifilter(function, numbers):
print n
print "\nfilter:"
numbers = number_generator()
for n in filter(function, numbers):
print n
出力:
itertools.ifilter: 利回り0 利回り1 1 利回り2 2 停止 filter: 利回り0 利回り1 利回り2 停止 1 2
あなたの理解は正しいです:唯一の違いは、ifilter
がイテレータを返すのに対し、filter
を使用することは次のように呼び出すことです。
_list(ifilter(...))
_
PEP 289 がfilterとifilterについて何を言っているかも興味があるかもしれません:
リスト内包表記により、
filter()
およびmap()
の必要性が大幅に減少しました。同様に、ジェネレータ式はitertools.ifilter()
とitertools.imap()
の必要性を最小限に抑えることが期待されています。 [...]
また、Python-3ではifilter
がfilter
になったことに注意してください(したがって、itertoolsから削除されました)。
ifilter
は、リストではなくジェネレーターを返します。
ジェネレーターは、リスト全体を最初に割り当てるのではなく、必要に応じてその場でアイテムを作成します。 ifilter
とfilter
の唯一の違いはそれです
ここで、違いを見ることができます:
filter(function、iterable) :関数がtrueを返すiterableの要素からリストを作成します。
itertools.ifilter(predicate、iterable) :要素を反復可能な戻り値からフィルタリングする iteratorを作成します述語がTrueであるものだけ。
つまり、「ifiltered」アイテムを取得するには、返されたイテレータで反復する必要がありますが、「filter」は、反復を必要とせずにリスト内のすべての要素を返します。