静かなる名辞

pythonとプログラミングのこと

【python】複数のin演算子をまとめる方法

はじめに

 こういう条件を考える。

>>> s = "hoge! fuga! piyo!"
>>> if "hoge" in s and "fuga" in s and "piyo" in s:
...     print("fizz!")
... 
fizz!

 壮絶にまどろっこしい。できればこんな風に書きたい。

>>> if ("hoge", "fuga", "piyo") in s:

 ただ、こんな文法はpythonにはない(というかstrの__contains__メソッドあたりがこういう引数を想定していない)。

 なので、これに近づける方法を考える。

all()とany()

 どちらも組み込み関数である。all()は論理積、any()は論理和に対応する。

 実行例はこんな感じ。

>>> all([False,False])
False
>>> all([False,True])
False
>>> all([True,True])
True
>>> any([False,False])
False
>>> any([False,True])
True

 これを踏まえ、冒頭のコードを以下のように書き換えてみる。

>>> s = "hoge! fuga! piyo!"
>>> if all(x in s for x in ("hoge", "fuga", "piyo")):
...     print("fizz!")
... 
fizz!

 まだちょっとダルい。mapでも書いてみる。

>>> s = "hoge! fuga! piyo!"
>>> ins_f = lambda x:x in s
>>> if all(map(ins_f, ("hoge", "fuga", "piyo"))):
...     print("fizz!")
... 
fizz!

 これはエレガントな感じがする。一行増えているけど。

 anyもまったく同様にやるだけなので、説明は省略。

注意

 ドキュメントを読むとわかるのだが、all(), any()は機能的にはとても単純なようだ。

2. 組み込み関数 — Python 3.6.5 ドキュメント

 それは別に良いのだが、先に引数をすべて渡す必要があるせいで、リストを引数に渡した場合、短絡評価されない(というか短絡評価する前に計算してしまっているので無意味)という問題がある。

 all(), any()を使うときは引数をジェネレータにしてあげた方が良いだろう。

まとめ

 この記事の方法を使うと、複数のin演算子が入るような場合にまとめて簡潔に書くことができる。

 あまり使う機会は多くないかもしれないが、参考にしてほしい。