条件式では複数の条件を組み合わせるために and
、or
、not
を使います。
本記事では初心者の方がつまずきやすい優先順位や短絡評価まで、豊富な例と出力結果つきで丁寧に解説します。
読みやすさと誤動作防止のコツも押さえて、今日から安心して条件式を書けるようになりましょう。
Pythonの条件式 and/or/not の基本
and(全ての条件が真なら真)
基本の考え方
A and B
は、A も B も真のときに真になります。
どちらか一方でも偽なら偽です。
Python では 0 や空文字、空リストなどは偽として扱われる(真偽値コンテキスト)ため、「真偽値に変換した結果」で判断されます。
下のコードでは、年齢が18歳以上かつ会員フラグが真のときに「購入可能」と表示します。
# and の基本例: 両方の条件を満たす必要がある
age = 20
is_member = True
if age >= 18 and is_member:
print("購入可能")
else:
print("購入不可")
購入可能
真偽値以外の値でも動く理由
Python では and
はブール値ではなく「オペランドそのもの」を返します。
詳細は後述しますが、実務では if
文の条件部に置く限り、この性質で困ることは多くありません。
or(どれか1つが真なら真)
基本の考え方
A or B
は、A か B のどちらかが真なら真になります。
両方とも偽のときだけ偽です。
# or の基本例: いずれかの条件を満たせば良い
has_coupon = False
is_premium = True
if has_coupon or is_premium:
print("割引適用")
else:
print("割引なし")
割引適用
not(真偽を反転する)
基本の考え方
not A
は、A の真偽を反転します。
真なら偽、偽なら真です。
# not の基本例: 否定を使った分岐
email = ""
if not email: # 空文字は偽として扱われる
print("メールアドレスを入力してください")
else:
print("送信します")
メールアドレスを入力してください
参考: 真偽表(ブール値のみ)
A | B | A and B | A or B |
---|---|---|---|
True | True | True | True |
True | False | False | True |
False | True | False | True |
False | False | False | False |
優先順位と短絡評価のポイント(Python)
演算子の優先順位(not > and > or)
覚えるべき最小セット
Python の論理演算の優先順位は not > and > or です。
つまり、同じ行に混在すると not
が最優先、次に and
、最後に or
が評価されます。
# 優先順位の違いを確認
a = True or False and False # and が先、次に or
b = (True or False) and False # 括弧で明示的に変える
print(a) # True or (False and False) -> True or False -> True
print(b) # (True or False) and False -> True and False -> False
True
False
括弧()で優先順位と意図を明確にする
読みやすさのための括弧
コードは動けば良いだけでなく、意図が一目で分かることが重要です。
優先順位を覚えていても、複雑になりそうなときは積極的に括弧でグループ化しましょう。
# 括弧がある場合とない場合の比較
is_adult = True
is_staff = False
is_admin = True
# なし: 読み手は優先順位を解読する必要がある
result1 = is_adult and is_staff or is_admin
# あり: 「成人 かつ (スタッフ or 管理者)」が明確になる
result2 = is_adult and (is_staff or is_admin)
print(result1) # True
print(result2) # True
True
True
見た目は同じ結果ですが、意図が変わる可能性があるロジックでは常に括弧で示すことをおすすめします。
短絡評価(ショートサーキット)の挙動
左から右へ、決まったら止まる
短絡評価とは、and
と or
が左から順に評価し、結果が決まった時点で残りを評価しない性質です。
A and B
: A が偽なら、その時点で偽と決まるので B は評価されません。A or B
: A が真なら、その時点で真と決まるので B は評価されません。
# 短絡評価の観察用に、副作用のある関数を定義
def left_true():
print("left_true() が呼ばれた")
return True
def left_false():
print("left_false() が呼ばれた")
return False
def right():
print("right() が呼ばれた")
return True
# and: 左が偽なら右は呼ばれない
print("== and の短絡評価 ==")
print(left_false() and right()) # right() は呼ばれない
# or: 左が真なら右は呼ばれない
print("== or の短絡評価 ==")
print(left_true() or right()) # right() は呼ばれない
== and の短絡評価 ==
left_false() が呼ばれた
False
== or の短絡評価 ==
left_true() が呼ばれた
True
関数呼び出しの抑制や安全なアクセス(例: オブジェクトが None ならプロパティを見に行かない)に役立ちます。
and/or/not の書き方のコツと注意点
and と or の組み合わせは括弧でグループ化
誤読を避ける実例
複合条件では、括弧で意図を固定しましょう。
下の2つは見た目が似ていますが、評価順で意味が変わります。
is_active = True
is_staff = False
is_admin = False
# 例1: (アクティブ かつ スタッフ) または 管理者
allow1 = (is_active and is_staff) or is_admin
# 例2: アクティブ かつ (スタッフ または 管理者)
allow2 = is_active and (is_staff or is_admin)
print(allow1) # False
print(allow2) # False
False
False
今回はたまたま同じ結果ですが、括弧の違いでビジネスロジックが変わるケースは多いです。
常に括弧でグループ化し、意図を明示しましょう。
not の適用範囲を小さくして読みやすく
なるべく肯定形で書く
否定の重ね掛けは読みにくいため、比較演算子やメンバーシップ演算子の否定形を活用し、not
の適用範囲を小さくします。
# 悪い例: 否定が重なって読みにくい
status = "pending"
if not (status == "approved"):
print("承認されていません")
# 良い例: 否定形の演算子を使う
if status != "approved":
print("承認されていません")
# in / not in を活用
items = ["a", "b"]
if "c" not in items: # not ("c" in items) より読みやすい
print("c は含まれていません")
承認されていません
承認されていません
c は含まれていません
デ・モルガンの法則(not(A and B)→(not A) or (not B))
否定を分配して読みやすくする
デ・モルガンの法則は、複雑な否定条件を分かりやすく書き換えるのに便利です。
age = 15
has_consent = False
# 2つの書き方は等価
deny1 = not (age >= 18 and has_consent)
deny2 = (age < 18) or (not has_consent)
print(deny1, deny2) # どちらも True
True True
ビット演算子(&, |)と論理演算子(and, or)の混同に注意
役割の違いを理解する
& や | はビット演算(整数やビット列向け)、and や or は論理演算(真偽の組み合わせ)です。
両者を混同するとバグの温床になります。
特に &
と |
は短絡評価しません。
観点 | 論理演算子(and, or, not) | ビット演算子(&, | , ^, ~) |
---|---|---|---|
主目的 | 真偽値の組み合わせ | 整数の各ビット操作(配列型で要素ごと演算のことも) | |
短絡評価 | あり(and, or) | なし(両辺を必ず評価) | |
返り値 | オペランドそのもの(後述) | 型に応じた演算結果(例: int) | |
典型例 | 条件分岐、ガード節 | フラグビットの合成、マスク |
# and/or と &/| の違いを体感
def f():
print("f() 呼び出し")
return True
def g():
print("g() 呼び出し")
return False
print("== 論理演算 ==")
print(f() and g()) # g() は呼ばれる(左が True のため)
print(f() or g()) # g() は呼ばれない(左が True のため)
print("== ビット演算 ==")
print(f() & g()) # 両方とも必ず呼ばれる
print(1 | 2, 1 & 2) # 1|2=3, 1&2=0 (ビット演算)
== 論理演算 ==
f() 呼び出し
g() 呼び出し
False
f() 呼び出し
True
== ビット演算 ==
f() 呼び出し
g() 呼び出し
False
3 0
補足: and/or はブール値ではなくオペランドを返す
Python の and
と or
は True/False ではなく、条件評価に使った値そのものを返します。
この性質は「デフォルト値の選択」などに便利ですが、型が混ざると戸惑うことがあります。
print("" or "fallback") # 左が偽("")のため右の値 "fallback" を返す
print([1, 2] and 999) # 左が真のため右を返す -> 999
print([] and [1]) # 左が偽のため左を返す -> []
print(0 or 10) # 0 は偽なので 10
print(bool([] and [1])) # 真偽が必要なら bool(...) で包む
fallback
999
[]
10
False
if 文の条件部では真偽として解釈されるため違和感は小さいですが、値として受け取るときは返り値の型に注意しましょう。
例で学ぶ条件式の書き方(Python)
and で複数条件を満たす
実例: 年齢と会員種別の確認
2つの条件が同時に満たされたときだけ処理を進める例です。
def can_purchase(age: int, is_member: bool) -> bool:
# 18歳以上 かつ 会員のみ購入可
return age >= 18 and is_member
print(can_purchase(20, True)) # 20歳の会員
print(can_purchase(16, True)) # 16歳の会員
print(can_purchase(25, False)) # 25歳の非会員
True
False
False
or でいずれかの条件を満たす
実例: 送料無料の判定
クーポンがあるか、またはプレミアム会員なら送料無料にします。
def is_free_shipping(has_coupon: bool, is_premium: bool) -> bool:
# どちらかが True なら True
return has_coupon or is_premium
print(is_free_shipping(False, False))
print(is_free_shipping(True, False))
print(is_free_shipping(False, True))
False
True
True
not で否定して分岐する
実例: ログイン状態の確認
否定を使うと「満たしていないときに早めに抜ける」書き方ができます。
def proceed_if_authenticated(is_authenticated: bool) -> str:
if not is_authenticated:
return "ログインが必要です"
# ここから先は認証済み
return "処理を続行します"
print(proceed_if_authenticated(False))
print(proceed_if_authenticated(True))
ログインが必要です
処理を続行します
and/or でガード節(早期リターン)を書く
入れ子を浅くして読みやすくする
ガード節とは、異常条件を先に判定して早期に関数を抜ける書き方です。
and
と or
を組み合わせて、単一の条件にまとめるとスッキリします。
def register_user(name: str | None, age: int | None) -> str:
# ガード1: 必須入力のチェック (どれか欠けていたら早期リターン)
if name is None or name == "" or age is None:
return "名前と年齢は必須です"
# ガード2: 値域チェック (18歳未満はお断り)
if not (0 <= age <= 120) or age < 18:
return "対象年齢外です"
# ここまで来れば登録可能
return f"登録完了: {name} さん({age}歳)"
print(register_user("", 20)) # name が空
print(register_user("Taro", None)) # age が None
print(register_user("Hanako", 15)) # 15歳
print(register_user("Ken", 25)) # 正常
名前と年齢は必須です
名前と年齢は必須です
対象年齢外です
登録完了: Ken さん(25歳)
複数条件をひとつのガードにまとめると、メインの処理が左に寄り、読みやすい「ハッピーパス」になります。
まとめ
本記事では、Python の条件式で使う and
、or
、not
の基本から、優先順位(not > and > or)・括弧による明示・短絡評価までを解説しました。
さらに、デ・モルガンの法則による読みやすい書き換えや、ビット演算子と論理演算子の混同という落とし穴も確認しました。
実務では、括弧で意図を示し、否定の範囲を最小化し、必要に応じて bool(...)
で明確にするのが安全です。
今日紹介した例を手元で動かし、短絡評価と真偽の感覚を体で覚えていきましょう。