2011年12月4日日曜日

Python組み込み関数(any 関数 と all 関数)

今回は小ネタです。

この前ソースを眺めていたら、見慣れない関数があった。例えば次のようなコードである。

if not filename.startswith('/') or \
                any(filename.endswith(x) for x in ignore_concat):

この中で any が使われているが、なんだこれは?。・・・ということで調べてみました。

組み込み関数

any はPython組み込み関数である。似た関数として all というものもあるそうだ。

any(iterable)
iterable のいずれかの要素が真ならば True を返します。 iterable が空なら False を返します。以下のコードと等価です。
def any(iterable):
    for element in iterable:
        if element:
            return True
    return False
バージョン 2.5 で追加
 
all(iterable)
iterable の全ての要素が真ならば (もしくは iterable が空ならば) True を返します。以下のコードと等価です。
def all(iterable):
    for element in iterable:
        if not element:
            return False
    return True
バージョン 2.5 で追加
参考: Python 2.6ja2 documentation - 組み込み関数

イテレータを渡してあげれば、anyだったら要素が一個でも真ならTrueを返すのか、なるほど。Python2.5 から実装されたので、結構前からあるんだな。

any と all を使ってみる

せっかくなので使ってみる。

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

True と False の値をもったリストオブジェクトを any と all に渡してみると、any は True になって all は False になった。

>>> a = 5
>>> test2 = [a>3, a==6, a<9]
>>> any(test2)
True
>>> all(test2)
False

次に変数の条件式をリストオブジェクトに入れて、 any と all に渡してみる。any は True になって all は False になった。

>>> test3 = {'satou':7,'suzuki':6,'takahashi':8,'tanaka':5}
>>> any(v>=6 for v in test3.values())
True
>>> all(v>=6 for v in test3.values())
False

更に辞書型オブジェクトの値部分をFor文で回して条件式にする構文を、any と all に渡してみる。any は True になって all は False になった。

例3の関数に渡すパラメータはジェネレータ式となっている。

参考: Python 2.6ja2 documentation - ジェネレータ式

リスト内包表記で記述することも可能だ。

>>> test3 = {'satou':7,'suzuki':6,'takahashi':8,'tanaka':5}
>>> any([v>=6 for v in test3.values()])
True
>>> all([v>=6 for v in test3.values()])
False

参考: Python 2.6ja2 documentation - ジェネレータ式とリスト内包表記

しかし特にany関数では、ジェネレータ式を使用した方がパフォーマンスが良いと思う。


特に例3の構文は、いろいろと応用できる。

any と all は頻繁ではないかもしれませんが、よく使用するロジックです。このため、これらの組み込み関数を利用すれば、かなり便利になるでしょう。

( 2011/12/8 - 微妙に間違っている気がしたので、内容を若干変更しました。 )