複数の条件をorやandでつないだif文は、すぐに長く読みにくくなります。
そこで活躍するのがany()
とall()
です。
これらを使えば複数条件を1行で判定でき、しかもショートサーキット(早期終了)によって無駄な計算を避けられます。
基本から実用パターンと注意点まで丁寧に解説します。
Pythonのany()とall()の基本
何ができる 使い方と条件判定の考え方
any()
はイテラブル内に1つでも真があればTrue
、all()
は全てが真のときだけTrue
を返します。
ここでの「真」はPythonのいわゆる真偽値判定(Truthiness)で、非空文字列や非0の数値は真、0や空文字""
、None
は偽として扱われます。
複数の条件をまとめて評価し、結果だけほしいときに最適です。
# any() と all() の最小例
values = [True, False, False]
print("any(values):", any(values)) # 1つでも True があれば True
print("all(values):", all(values)) # 1つでも False があれば False
values2 = [1, 0, "hello"] # 1 と "hello" は真、0 は偽
print("any(values2):", any(values2))
print("all(values2):", all(values2))
any(values): True
all(values): False
any(values2): True
all(values2): False
引数はイテラブル1つだけ
any()
とall()
は「単一のイテラブル」を引数に取る関数です。
複数の引数を並べて渡すことはできません。
正しくはリストやタプル、ジェネレータ式などに条件を並べます。
# 正しい: イテラブル(リスト)を1つ渡す
print(any([True, False, False]))
# 間違い: 引数を並べて渡すと TypeError になる
try:
print(any(True, False, False)) # 引数が3つ -> エラー
except TypeError as e:
print("TypeError:", e)
True
TypeError: any() takes exactly one argument (3 given)
返り値はTrueかFalseだけ
両者とも返すのは常にbool
型です。
andやorのようにオペランドそのものを返すことはありません。
result_any = any([1, 2, 3]) # 全て真
result_all = all([1, 2, 3])
print(result_any, type(result_any))
print(result_all, type(result_all))
True <class 'bool'>
True <class 'bool'>
空の場合 anyはFalse allはTrue
空のイテラブルに対してはany([])
はFalse
、all([])
はTrue
です。
これは論理演算の単位元(恒等値)の性質によるものです。
print(any([])) # 要素が1つも「真」でない -> False
print(all([])) # 反例(偽)が1つもない -> True
False
True
途中で評価を止めるショートサーキット
any()は最初のTrueで、all()は最初のFalseで評価を打ち切ります。
不要な計算をしないためパフォーマンス上の利点があります。
def check(n: int) -> bool:
print(f"check({n}) を評価")
return n > 0
nums = [-1, 0, 5, 10]
print("any(nums>0):", any(check(n) for n in nums)) # 5でTrueになった時点で打ち切り
nums2 = [1, 2, 0, 3]
print("all(nums2>0):", all(check(n) for n in nums2)) # 0でFalseになった時点で打ち切り
check(-1) を評価
check(0) を評価
check(5) を評価
any(nums>0): True
check(1) を評価
check(2) を評価
check(0) を評価
all(nums2>0): False
any()の使い方 初心者向け例
複数条件のうち1つでもTrueならTrue
アクセス権限など「いずれかを満たせばOK」の場面で読みやすく書けます。
user_roles = {"viewer", "moderator"} # 重複なしの集合
is_admin = "admin" in user_roles
is_staff = "staff" in user_roles
is_moderator = "moderator" in user_roles
can_access = any([is_admin, is_staff, is_moderator])
print("can_access:", can_access)
can_access: True
文字列の部分一致やキーワード検出に便利
文章に特定の単語が1つでも含まれるかを素早く判定できます。
実際の抽出は別途行い、存在判定はany()
で即座に可能です。
text = "今日は雨なので傘を持っていこう"
keywords = ["雪", "雨", "嵐"]
has_weather_word = any(kw in text for kw in keywords) # 存在の有無
hits = [kw for kw in keywords if kw in text] # 実際に含まれた語
print("存在判定:", has_weather_word)
print("一致キーワード:", hits)
存在判定: True
一致キーワード: ['雨']
エラーやフラグの有無を1行で判定
エラーメッセージのコレクションに1つでも内容があればエラーあり、と判定できます。
空文字は偽、非空文字は真です。
errors = {"email": "", "password": "短すぎます", "age": ""}
has_error = any(msg for msg in errors.values())
print("エラーあり?:", has_error)
エラーあり?: True
入力バリデーションを簡潔に書く
必須項目の「欠損が1つでもあるか」をまとめて確認できます。
0やFalseを欠損扱いにしないために、値の種類を限定して明示的に比較するのが安全です。
payload = {"name": "Alice", "email": "", "age": None, "newsletter": False}
# None または 空文字 "" が1つでもあれば「欠損あり」
missing = any(v in (None, "") for v in payload.values())
print("欠損あり?:", missing)
欠損あり?: True
if文を短く 1行で読みやすく
orを何度も書く代わりに、条件を並べるだけで意図が明確になります。
x, y, z = 0, 5, -3
# 従来の or の列挙
if (x < 0) or (y < 0) or (z < 0):
print("A: 負の値が含まれます")
# any() で1行
if any(v < 0 for v in (x, y, z)):
print("B: 負の値が含まれます")
A: 負の値が含まれます
B: 負の値が含まれます
- 関連記事:if-elif-else文の基本と書き方
all()の使い方 初心者向け例
全ての条件がTrueならTrue
入会条件や実行前チェックなど「全て満たす必要がある」場面に適します。
email_ok = True
password_ok = True
age_ok = True
can_register = all([email_ok, password_ok, age_ok])
print("登録可能?:", can_register)
登録可能?: True
必須入力チェック Noneや空文字を含まない
必須キーだけを対象にして、全て埋まっているかを一括判定します。
form = {"name": "Bob", "email": "bob@example.com", "phone": "090-0000", "note": ""}
required = ("name", "email") # 必須は name と email
all_filled = all(form[k] not in (None, "") for k in required)
print("必須埋め済み?:", all_filled)
必須埋め済み?: True
数値の範囲チェックをまとめて判定
配列や複数入力がすべて許容範囲内かをまとめて確認します。
scores = [88, 76, 95]
print("全て 0..100?:", all(0 <= s <= 100 for s in scores))
scores2 = [88, -1, 101]
print("全て 0..100?:", all(0 <= s <= 100 for s in scores2))
全て 0..100?: True
全て 0..100?: False
複数フラグが全てONかを確認
設定スイッチがすべて有効化されているかを簡単にチェックできます。
flags = {"feature_a": True, "feature_b": True, "feature_c": True}
ready = all(flags.values())
print("全機能ON?:", ready)
全機能ON?: True
ネストしたifを減らす 1行でスッキリ
深いネストは読みづらくなります。
all()
で条件を並べると意図が明確になります。
user = {"active": True, "email_verified": True, "two_factor_on": False}
# ネストした if
if user["active"]:
if user["email_verified"]:
if user["two_factor_on"]:
print("OK")
else:
print("NG")
# all() で1行に
if all([user["active"], user["email_verified"], user["two_factor_on"]]):
print("OK (all)")
else:
print("NG (all)")
NG
NG (all)
実用パターンと注意点
内包表記やジェネレータ式と組み合わせる
大きなデータではジェネレータ式の方が省メモリです。
any([条件 for x in data])
は一度リストを作るためメモリを使いますが、any(条件 for x in data)
は項目を順に生成して評価します。
data = [1, 2, -1, 4]
# リスト内包表記: 中間リストを作る
print("list:", any([x < 0 for x in data]))
# ジェネレータ式: 中間リストを作らない
print("gen :", any(x < 0 for x in data))
list: True
gen : True
条件式をリストに並べて読みやすくする
複数の検証を「チェックリスト」として並べ、最後にall()
でまとめると意図が伝わりやすくなります。
コメントで条件の意味も残しやすいです。
age = 24
name = "Alice"
email = "alice@example.com"
conditions = [
18 <= age <= 120, # 年齢が妥当
name.isalpha(), # 名前は英字のみ
("@" in email) and ("." in email), # メールっぽい形式
]
if all(conditions):
print("検証OK")
else:
print("検証NG")
検証OK
andやorとの違い anyとallは真偽値を返す
any()
とall()
は常にTrue/False
を返します。
一方、and
/or
演算子はオペランドそのものを返すため、値の型が変わって思わぬバグを生むことがあります。
# and / or はオペランドを返す
print("and/or:", "OK" and 10, 0 or "fallback") # -> 10 と "fallback"
# any / all は常に bool
print("any/all:", any(["OK", 10]), all(["OK", 10])) # -> True と True
# 型の違いを確認
print("types :", type("OK" and 10), type(any(["OK", 10])))
and/or: 10 fallback
any/all: True True
types : <class 'int'> <class 'bool'>
以下の表で違いを整理します。
項目 | any() / all() | and / or |
---|---|---|
入力 | イテラブル1つ | 2つのオペランド |
返り値 | 常に bool | 片方のオペランド |
短絡評価 | あり(最初のTrue/Falseで停止) | あり(左で決まれば右を評価しない) |
主用途 | 複数条件の集合評価 | 条件の連結、値のフォールバック |
注意点 | 空イテラブルの扱い | 型がboolとは限らない |
間違いがち 引数を複数ではなく1つのイテラブルで渡す
複数の引数を並べて渡すのは誤りです。
正しくはリストやタプル、ジェネレータ式で1つにまとめましょう。
# 誤りの例
try:
all(True, True)
except TypeError as e:
print("TypeError:", e)
# 正しい例
print(all((True, True)))
TypeError: all() takes exactly one argument (2 given)
True
パフォーマンス 早期終了で無駄な計算を避ける
ショートサーキットにより、重い計算を必要最小限に抑えられます。
下の例では目的の結果が確定した時点で後続の要素を評価しません。
def expensive(n: int) -> bool:
# 実際にはAPI呼び出しや重い計算を想定
print(f"expensive({n}) を実行")
return n % 5 == 0
nums = [1, 2, 10, 20]
print("any:", any(expensive(n) for n in nums)) # 10でTrueになり20は呼ばれない
nums2 = [10, 15, 2, 20]
print("all:", all(expensive(n) for n in nums2)) # 2でFalseになり20は呼ばれない
expensive(1) を実行
expensive(2) を実行
expensive(10) を実行
any: True
expensive(10) を実行
expensive(15) を実行
expensive(2) を実行
all: False
大規模データでは中間リストを作らないジェネレータ式(条件 for x in data)
と組み合わせるのが実用的です。
メモリ節約と早期終了の両方の恩恵を受けられます。
まとめ
any()
は「1つでも満たす」、all()
は「全て満たす」という直感的な規則で、複数条件の判定を1行で明快に書けます。
イテラブルは1つだけ渡す、空のときはanyがFalse、allがTrue、そしてショートサーキットで無駄な計算をしないという3点を押さえれば、日常のバリデーションや探索、フラグ判定がすっきり整理できます。
さらにand
/or
との違いを理解し、any(条件 for ...)
やall([...])
といった書き方を適材適所で使い分けることで、読みやすく保守性の高いコードになります。