【Python】filter 関数の使い方と実行結果

Python の組み込み関数 filterフィルター の使い方です。

filter 関数で、iterableイテラブル なオブジェクトから(リストやジェネレーターなどの反復可能なオブジェクトから)、不要な要素を除外じょがいします。

そのコード例と、実行結果を載せました。

あと、『エラーになったコード例』も書きました。

エラーになったコード例

filter 関数で、エラーになったコードれいです。

(Python) filter(function, iterable)

filter()
TypeError: filter expected 2 arguments, got 0
filter(None)
TypeError: filter expected 2 arguments, got 1
filter(None, None)
TypeError: 'NoneType' object is not iterable
filter(None, 100)
TypeError: 'int' object is not iterable
filter(function=None, iterable=[1, 2, 3])
TypeError: filter() takes no keyword arguments
datas = filter(True, [1, 2, 3])
print(list(datas)) # TypeError
TypeError: 'bool' object is not callable
datas = filter('abc', [1, 2, 3])
print(list(datas)) # TypeError
TypeError: 'str' object is not callable

filter 関数の戻り値は『イテレーター』でした

filter 関数の戻りは、リストではなくて、『filter オブジェクト』という名前の iteratorイテレーター になっていました。

(Python) filter(function, iterable)

(Python) リストからビューおよびイテレータへ(filter 関数はイテレータを返します)

(Python) iterable イテラブル(反復可能オブジェクト)

(Python) iterator イテレーター(データの流れを表現するオブジェクト)

(Python) ラムダ式

(Python) ラムダ (lambda)

filter(lambda x: x >= 2, [1, 2, 3])
<filter object at 0x0000000000000000>

なので、filter 関数から『結果を取り出すとき』は、戻り値を『tupleタプル 関数 や list 関数』に渡したり、『next 関数や for ぶん』に渡したらできました。

(Python) tuple([iterable])

datas = filter(lambda x: x >= 2, [1, 2, 3])
print(tuple(datas))
(2, 3)

(Python) class list([iterable])

datas = filter(lambda x: x >= 2, [1, 2, 3])
print(list(datas))
[2, 3]

(Python) next(iterator[, default])

datas = filter(lambda x: x >= 2, [1, 2, 3])
print(next(datas))
print(next(datas))
2
3

(Python) for 文

datas = filter(lambda x: x >= 2, [1, 2, 3])
for data in datas:
    print(data)
2
3

tuple を渡した結果

filter 関数に、tupleタプル を渡した結果です。

(Python) filter(function, iterable)

(Python) tuple([iterable])

(Python) functools.partial(func, /, *args, **keywords)

(Python) operator.is_(a, b)

(Python) operator.is_not(a, b)

(Python) ラムダ式

(Python) isinstance(object, classinfo)

datas = filter(None, ())
print(tuple(datas))
()
datas = filter(None, (0, None, 5, 'abc'))
print(tuple(datas))
(5, 'abc')
from functools import partial
from operator import is_
# is_(None, 0), is_(None, None), is_(None, 5), ...
datas = filter(partial(is_, None), (0, None, 5, 'abc'))
print(tuple(datas))
(None,)
from functools import partial
from operator import is_not
# is_not(None, 0), is_not(None, None), is_not(None, 5), ...
datas = filter(partial(is_not, None), (0, None, 5, 'abc'))
print(tuple(datas))
(0, 5, 'abc')
datas = filter(lambda x: x is not None, (0, None, 5, 'abc'))
print(tuple(datas))
(0, 5, 'abc')
datas = filter(lambda x: isinstance(x, str), (0, None, 5, 'abc'))
print(tuple(datas))
('abc',)

list を渡した結果

filter 関数に、listリスト を渡した結果です。

(Python) filter(function, iterable)

(Python) class list([iterable])

(Python) functools.partial(func, /, *args, **keywords)

(Python) operator.is_(a, b)

(Python) operator.is_not(a, b)

(Python) ラムダ式

(Python) isinstance(object, classinfo)

datas = filter(None, [])
print(list(datas))
[]
datas = filter(None, [0, None, 5, 'abc'])
print(list(datas))
[5, 'abc']
from functools import partial
from operator import is_
# is_(None, 0), is_(None, None), is_(None, 5), ...
datas = filter(partial(is_, None), [0, None, 5, 'abc'])
print(list(datas))
[None]
from functools import partial
from operator import is_not
# is_not(None, 0), is_not(None, None), is_not(None, 5), ...
datas = filter(partial(is_not, None), [0, None, 5, 'abc'])
print(list(datas))
[0, 5, 'abc']
datas = filter(lambda x: x is not None, [0, None, 5, 'abc'])
print(list(datas))
[0, 5, 'abc']
datas = filter(lambda x: isinstance(x, str), [0, None, 5, 'abc'])
print(list(datas))
['abc']

generator オブジェクトを渡した結果

filter 関数に、generatorジェネレーター オブジェクトを渡した結果です。

(Python) filter(function, iterable)

(Python) ジェネレータ式(Python チュートリアル)

(Python) ジェネレータ式とリスト内包表記(Python 言語リファレンス)

(Python) ジェネレータ式 (generator expression)(Python 言語リファレンス)

(Python) ジェネレータ (generator)(Python チュートリアル)

(Python) ラムダ式

src_datas = (x for x in [-10, -5, 0, 5, 10])
print(src_datas)
datas = filter(None, src_datas)
print(list(datas))
<generator object <genexpr> at 0x0000000000000000>
[-10, -5, 5, 10]
src_datas = (x for x in [-10, -5, 0, 5, 10])
print(src_datas)
datas = filter(lambda x: x >= 0, src_datas)
print(list(datas))
<generator object <genexpr> at 0x0000000000000000>
[0, 5, 10]
def generate_datas():
    for x in [-10, -5, 0, 5, 10]:
        yield x

print(generate_datas)

src_datas = generate_datas()
print(src_datas)

datas = filter(lambda x: x >= 0, src_datas)
print(list(datas))
<function generate_datas at 0x0000000000000000>
<generator object generate_datas at 0x0000000000000000>
[0, 5, 10]

iterator オブジェクトを渡した結果

filter 関数に、iteratorイテレーター オブジェクトを渡した結果です。

(Python) filter(function, iterable)

(Python) iter(object[, sentinel])

(Python) イテレータ (iterator)(Python チュートリアル)

(Python) イテレータ (iterator)(関数型プログラミング HOWTO)

(Python) ラムダ式

src_datas = iter([-10, -5, 0, 5, 10])
print(src_datas)
datas = filter(None, src_datas)
print(list(datas))
<list_iterator object at 0x0000000000000000>
[-10, -5, 5, 10]
src_datas = iter([-10, -5, 0, 5, 10])
print(src_datas)
datas = filter(lambda x: x >= 0, src_datas)
print(list(datas))
<list_iterator object at 0x0000000000000000>
[0, 5, 10]

複数の条件を設定した結果

filter 関数に『複数の条件』を指定した結果です。

複数の条件は、自作関数で実現することができました。

自作関数は、『lambda 式ラムダ しき』でも、普通の『関数定義』で作ったものでも、渡すことができました。

また、条件を分割して『filter 関数を繰り返し適用する方法』でも、同じ結果を得ることができました。

(Python) filter(function, iterable)

(Python) ラムダ式(Python チュートリアル)

(Python) ラムダ (lambda)(Python 言語リファレンス)

(Python) 関数を定義する(Python チュートリアル)

(Python) 関数定義(Python 言語リファレンス)

(Python) isinstance(object, classinfo)

試しに、x[0] が『文字列 (str)』で、x[1] が『None ではないもの』を選んでみました。

src_datas = [['abc', True], ['xyz', None], [None, True]]
func = lambda x: isinstance(x[0], str) and (x[1] is not None)
datas = filter(func, src_datas)
print(list(datas))
[['abc', True]]
src_datas = [['abc', True], ['xyz', None], [None, True]]

def func(x):
    if isinstance(x[0], str):
        if x[1] is not None:
            return True
    return False

datas = filter(func, src_datas)
print(list(datas))
[['abc', True]]

条件を分割して『filter 関数を繰り返し適用する方法』でもできました。

src_datas = [['abc', True], ['xyz', None], [None, True]]

temp_datas = filter(lambda x: isinstance(x[0], str), src_datas)
# list(temp_datas): [['abc', True], ['xyz', None]]

datas = filter(lambda x: x[1] is not None, temp_datas)
print(list(datas))
[['abc', True]]

『filter 関数』と『内包表記』は、どちらが良いのか?

自分は、『内包表記ないほうひょうき』のほうが、簡単で分かりやすくて良かったです。

filter 関数と同じような処理は、『リスト内包表記 []』や『ジェネレータ式 ()』で書くことができました。

(Python) 組み込み関数 (built-in function) のところにも、『Python のビルトイン関数 map() と filter() は、機能がジェネレータ式と重複しています』という説明がありました。

結果をリストで受け取るなら『かくカッコのリスト内包表記 []』が便利でしたし、遅延評価にするなら『まるカッコのジェネレータ式 ()』が便利でした。

(Python) 内包表記の共通の構文要素

(Python) ジェネレータ式とリスト内包表記(Python 言語リファレンス)

(Python) ジェネレータ式 (generator expression)(Python 言語リファレンス)

(Python) generator expression(ジェネレータ式)(用語集)

(Python) list comprehension(リスト内包表記)(用語集)

内包表記などは、filter 関数とちがって、『lambda 式なし(自作関数なし)』で判定することができましたし、for 文も見えていて直感的でした。

さらに、リストのリストであっても、lambda 式を使うことなく、リストの要素を参照することができて、便利でした。

そういうわけで、filter 関数の使用は、機会があるたびに検討はしたものの、結局、内包表記ジェネレータ式を使うに至りました。

filter 関数よりも、内包表記などのほうが、機能的にも使いやすさ的にも、メリットが大きかったです。

実行速度の比較についてです。

Python マニュアルの『プログラミング FAQ』の中で、少しだけ言及げんきゅうがありました。

リストからアイテムを除去するコード例のところで、『filter 関数』と『ジェネレータ式』と『リスト内包表記』の速度について、触れていました。

(Python) How do you remove multiple items from a list (The list comprehension may be fastest.)

以上です。

スポンサーリンク
Python
シェアする(押すとSNS投稿用の『編集ページ』に移動します)
フォローする(RSSフィードに移動します)
スポンサーリンク
シラベルノート
タイトルとURLをコピーしました