閉じる

Pythonの条件式で使うand/or/notの基本と使い方・優先順位

条件式では複数の条件を組み合わせるために andornot を使います。

本記事では初心者の方がつまずきやすい優先順位や短絡評価まで、豊富な例と出力結果つきで丁寧に解説します。

読みやすさと誤動作防止のコツも押さえて、今日から安心して条件式を書けるようになりましょう。

Pythonの条件式 and/or/not の基本

and(全ての条件が真なら真)

基本の考え方

A and B は、A も B も真のときに真になります。

どちらか一方でも偽なら偽です。

Python では 0 や空文字、空リストなどは偽として扱われる(真偽値コンテキスト)ため、「真偽値に変換した結果」で判断されます。

下のコードでは、年齢が18歳以上かつ会員フラグが真のときに「購入可能」と表示します。

Python
# 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 のどちらかが真なら真になります。

両方とも偽のときだけ偽です。

Python
# or の基本例: いずれかの条件を満たせば良い
has_coupon = False
is_premium = True

if has_coupon or is_premium:
    print("割引適用")
else:
    print("割引なし")
実行結果
割引適用

not(真偽を反転する)

基本の考え方

not A は、A の真偽を反転します。

真なら偽、偽なら真です。

Python
# not の基本例: 否定を使った分岐
email = ""

if not email:  # 空文字は偽として扱われる
    print("メールアドレスを入力してください")
else:
    print("送信します")
実行結果
メールアドレスを入力してください

参考: 真偽表(ブール値のみ)

ABA and BA or B
TrueTrueTrueTrue
TrueFalseFalseTrue
FalseTrueFalseTrue
FalseFalseFalseFalse

優先順位と短絡評価のポイント(Python)

演算子の優先順位(not > and > or)

覚えるべき最小セット

Python の論理演算の優先順位は not > and > or です。

つまり、同じ行に混在すると not が最優先、次に and、最後に or が評価されます。

Python
# 優先順位の違いを確認
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

括弧()で優先順位と意図を明確にする

読みやすさのための括弧

コードは動けば良いだけでなく、意図が一目で分かることが重要です。

優先順位を覚えていても、複雑になりそうなときは積極的に括弧でグループ化しましょう。

Python
# 括弧がある場合とない場合の比較
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

見た目は同じ結果ですが、意図が変わる可能性があるロジックでは常に括弧で示すことをおすすめします。

短絡評価(ショートサーキット)の挙動

左から右へ、決まったら止まる

短絡評価とは、andor が左から順に評価し、結果が決まった時点で残りを評価しない性質です。

  • A and B: A が偽なら、その時点で偽と決まるので B は評価されません。
  • A or B: A が真なら、その時点で真と決まるので B は評価されません。
Python
# 短絡評価の観察用に、副作用のある関数を定義
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つは見た目が似ていますが、評価順で意味が変わります。

Python
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 の適用範囲を小さくします。

Python
# 悪い例: 否定が重なって読みにくい
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))

否定を分配して読みやすくする

デ・モルガンの法則は、複雑な否定条件を分かりやすく書き換えるのに便利です。

Python
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)
典型例条件分岐、ガード節フラグビットの合成、マスク
Python
# 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 の andor は True/False ではなく、条件評価に使った値そのものを返します

この性質は「デフォルト値の選択」などに便利ですが、型が混ざると戸惑うことがあります。

Python
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つの条件が同時に満たされたときだけ処理を進める例です。

Python
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 でいずれかの条件を満たす

実例: 送料無料の判定

クーポンがあるか、またはプレミアム会員なら送料無料にします。

Python
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 で否定して分岐する

実例: ログイン状態の確認

否定を使うと「満たしていないときに早めに抜ける」書き方ができます。

Python
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 でガード節(早期リターン)を書く

入れ子を浅くして読みやすくする

ガード節とは、異常条件を先に判定して早期に関数を抜ける書き方です。

andor を組み合わせて、単一の条件にまとめるとスッキリします。

Python
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 の条件式で使う andornot の基本から、優先順位(not > and > or)・括弧による明示・短絡評価までを解説しました。

さらに、デ・モルガンの法則による読みやすい書き換えや、ビット演算子と論理演算子の混同という落とし穴も確認しました。

実務では、括弧で意図を示し、否定の範囲を最小化し、必要に応じて bool(...) で明確にするのが安全です。

今日紹介した例を手元で動かし、短絡評価と真偽の感覚を体で覚えていきましょう。

この記事を書いた人
エーテリア編集部
エーテリア編集部

人気のPythonを初めて学ぶ方向けに、文法の基本から小さな自動化まで、実際に手を動かして理解できる記事を書いています。

クラウドSSLサイトシールは安心の証です。

URLをコピーしました!