Python | データ構造強化:any / all 条件判定

Python Python
スポンサーリンク

概要(any / all は「ひとつでも満たす」「全部満たす」を一瞬で判定する心臓部)

any と all は、並んだ条件の集合から「ひとつでも満たすか(any)」「全部満たすか(all)」を短く判定するための組み込み関数です。どちらもイテラブル(繰り返し可能なもの)を受け取り、要素を左から評価して結論が出た時点で止まる“短絡評価”を行います。これにより、無駄な計算を避けつつ読みやすいコードにできます。最重要ポイントは「真偽のルール(値の“truthiness”)」「ジェネレータとの併用」「短絡評価での順序最適化」です。

基本の使い方(ここが重要)

any は「ひとつでも True があれば True」

any(iterable) は要素の中に真(True)と評価されるものが一つでもあれば True、すべて偽なら False です。空のイテラブルは False になります。

print(any([False, False, True]))  # True
print(any([0, "", None]))         # False(すべて偽相当)
print(any([]))                    # False(空)
Python

all は「すべてが True なら True」

all(iterable) は全要素が真なら True、ひとつでも偽が混ざれば False です。空のイテラブルは True(“すべて満たす”の vacuous truth)になります。

print(all([True, 1, "x"]))  # True(全部真相当)
print(all([True, 0]))       # False(0 は偽相当)
print(all([]))              # True(空)
Python

真偽のルール(truthiness)を押さえる

Python では、0・空文字・空のコンテナ([]、{}、set())・None・False は偽、それ以外は基本的に真です。any / all はこの真偽規則で評価します。

重要ポイントの深掘り(短絡評価・順序最適化・ジェネレータ)

短絡評価(結論が出たら即終了)

any は True を見つけたらそこで打ち切り、all は False を見つけたら打ち切ります。これを前提に「軽い判定を前に、重い判定を後ろに」並べると高速化します。

def heavy(x): 
    # 重い処理の仮定
    return x**3 - x**2 + x > 10_000

xs = range(100000)
print(any((x % 2 == 0) and heavy(x) for x in xs))  # 先に軽い偶数チェック
Python

ジェネレータで“作らず流す”判定にする

内包表記の角括弧でリストを作る必要はありません。any / all はイテラブルを受け取れるので、丸括弧のジェネレータ式で遅延評価するとメモリが最小になります。

nums = range(10_000_000)
has_even = any(n % 2 == 0 for n in nums)      # リストを作らない
all_positive = all(n > 0 for n in nums)       # 条件だけ流す
Python

複数条件の組み合わせとガード

短絡評価を活かし、安いガード(None チェック、型チェック)を先頭に置いて安全に判定します。

rows = [{"score": 85}, {"score": None}, {"score": 92}]
ok = all(r["score"] is not None and r["score"] >= 0 for r in rows)
Python

実務での使いどころ(入力検証・権限チェック・検索条件の集約)

入力検証を一行にまとめる

フォームやAPIの必須項目の存在チェックは any / all が最短です。必須項目は all、任意項目の“いずれか必須”は any。

user = {"id": 101, "name": "alice", "email": ""}
required_ok = all(user.get(k) for k in ("id", "name"))      # 必須
contact_ok  = any(user.get(k) for k in ("email", "phone"))  # どちらかあればOK
Python

権限・ロールの判定

“必要権限のすべてを持っている”なら all、“いずれか持っていれば通す”なら any。

user_perms = {"read", "export"}
need_all   = {"read", "export"}
need_any   = {"write", "export"}

print(all(p in user_perms for p in need_all))  # True
print(any(p in user_perms for p in need_any))  # True
Python

検索条件の集約(AND / OR を読みやすく)

複数フィルタの合格判定を any / all へ寄せると、意図が明確で保守が楽になります。

checks = [
    lambda r: r["price"] < 1000,
    lambda r: r["stock"] > 0,
    lambda r: r["rating"] >= 4.5,
]
def passes_all(r): return all(check(r) for check in checks)
def passes_any(r): return any(check(r) for check in checks)
Python

よくある落とし穴の回避(空の扱い・真偽規則・例外を巻き込まない)

空イテラブルの戻り値を誤解しない

any([]) は False、all([]) は True。“all は全部満たす前提で、反例がないから True”という論理です。仕様として覚えておくとバグを防げます。

値そのものを渡すと意図がぶれる

数値や文字列のリストをそのまま any / all に渡すと「非ゼロ・非空=真」として扱われます。明示的な条件で評価するのが安全です。

nums = [1, 2, 0]
print(any(nums))                         # True(非ゼロあり)
print(all(n > 0 for n in nums))          # False(0 は不適)
Python

例外が起きやすい重い処理は関数に切り出す

any / all の中で例外が発生すると判定自体が中断します。try/except を含む安全な関数へ切り出し、その戻り値で判定しましょう。

def safe_int(s):
    try:
        return int(s)
    except ValueError:
        return None

strings = ["10", "x", "20"]
all_ints = all(safe_int(s) is not None for s in strings)
Python

例題で身につける(定番から一歩先まで)

例題1:偶数が“ひとつでも”あるか、全部が偶数か

nums = [1, 3, 5, 8]
print(any(n % 2 == 0 for n in nums))  # True
print(all(n % 2 == 0 for n in nums))  # False
Python

例題2:ファイル拡張子の安全チェック(軽い→重いの順)

names = ["report.pdf", "image.png", "README", "archive.zip"]
allowed = {".pdf", ".png"}

def suffix(name):
    i = name.rfind(".")
    return name[i:].lower() if i != -1 else ""

print(any(suffix(n) in allowed for n in names))   # 許可拡張子が“ひとつでも”ある
print(all(suffix(n) in allowed for n in names))   # 全部が許可拡張子か
Python

例題3:欠損値を含むスコアの検証

rows = [{"name":"alice","score":85},
        {"name":"bob","score":None},
        {"name":"cara","score":92}]
ok_scores = [r for r in rows if all([
    r["score"] is not None,
    r["score"] >= 80
])]
print(ok_scores)  # None を除外して80以上だけ
Python

例題4:権限チェック関数の実装

def has_all(user_perms, required):
    return all(p in user_perms for p in required)

def has_any(user_perms, candidates):
    return any(p in user_perms for p in candidates)

u = {"read", "export"}
print(has_all(u, {"read"}))             # True
print(has_all(u, {"read","write"}))     # False
print(has_any(u, {"write","export"}))   # True
Python

まとめ

any / all は「OR(ひとつでも)」「AND(全部)」をイテラブルに対して高速・簡潔に判定するための標準手段です。真偽のルール(0・空・None は偽)、短絡評価(結論が出たら即終了)、ジェネレータで“作らず流す”を押さえるだけで、入力検証、権限判定、検索条件の集約まで読みやすく堅牢に書けます。条件の順番は軽い→重いに最適化し、欠損ガードや安全関数で例外を封じる。まずは小さなデータで any / all を使い、for+flag から一歩進んだ“条件設計”の感覚を体に入れていきましょう。

タイトルとURLをコピーしました