Python: ブール論理
レッスン03では、論理演算子
and、or、notを含む演算子について学びました。このレッスンでは、コンピュータサイエンスで最も基本的な概念である真偽の判定に焦点を当てます。ブール論理は、すべての条件文、ループ制御、権限チェックの土台です。
1. ブール値:True と False
ブール値は True と False の2つだけです。これらはブール代数を創始したイギリスの数学者ジョージ・ブールにちなんで名付けられました。ブール代数は、現代のコンピューティングにおける「0と1」の理論的基礎です。
print(True) # 出力: True
print(False) # 出力: False
print(type(True)) # <class 'bool'>
比較演算子はブール値の結果を生成します:
print(5 > 3) # True
print(10 == 5) # False
print(7 <= 7) # True
print(3 != 3) # False
(1) ブール値は数値でもある
Pythonでは、True と False は実際には int のサブクラスです——True は 1、False は 0 に相当します:
print(True + True) # 2 (True=1、Trueが2つで2)
print(True * 10) # 10
print(False * 100) # 0
警告: Pythonでは
True == 1とFalse == 0が成り立ちますが(したがってTrue + Trueは2になります)、このように使ってはいけません。ブール値は論理判定のためのものであり、算術のためのものではありません。score + Trueのようなコードを書くと、読む人を混乱させます。
▶ サンプル:健康チェックの結果(難易度 ⭐)
# 比較演算子でブール値を生成する
age = 25
height = 175
weight = 70
is_adult = age >= 18 # True
is_tall = height > 170 # True
is_heavy = weight > 80 # False
print(f"Adult: {is_adult}")
print(f"Tall: {is_tall}")
print(f"Overweight: {is_heavy}")
# ブール値を直接出力する——これらは値であり、テキストではない
print(f"Adult AND Tall: {is_adult and is_tall}")
Output:
Adult: True
Tall: True
Overweight: False
Adult AND Tall: True
2. not:否定
not は「反転」を意味します——黒は白に、白は黒になります。
print(not True) # False
print(not False) # True
print(not (5 > 3)) # False (5>3はTrue、否定するとFalse)
not は主に2つの場面で使われます:
場面1:「条件を満たしていない」ことの確認
# 管理者ではない——バックエンドに入れない
is_admin = False
if not is_admin:
print("You do not have admin access.")
# 出力: You do not have admin access.
場面2:変数が空かどうかの確認
# ユーザーが名前を入力しなかったかチェック
username = ""
if not username:
print("Username cannot be empty!")
# 出力: Username cannot be empty!
ここにはPythonの「暗黙のブール変換」という仕組みがあります——空文字列 "" は条件判定で False と同等です。したがって、username が空文字列のとき、not username は True になります。どの値が「偽(falsy)」になるかは後で扱います。
ヒント:
notは「否定」を意味します。コードではif not is_admin:は「管理者でないなら」と読みます。
3. and:両方が True であること
and は「両方」を意味します——結果が True になるには両方の条件が真でなければなりません。どちらかが偽なら、結果は False です。
| 左辺 | 右辺 | 結果 |
|---|---|---|
| True | True | True |
| True | False | False |
| False | True | False |
| False | False | False |
age = 22
has_id = True
# 両方の条件を満たす必要がある
can_buy_alcohol = age >= 18 and has_id
print(can_buy_alcohol) # True (成人かつ身分証を所持)
# 別の場面:クレジットカードの申し込みには収入5万以上かつクレジットスコア600以上が必要
income = 80 # 千単位
credit_score = 650
qualified = income >= 50 and credit_score >= 600
print(f"Credit card application: {qualified}") # True
▶ サンプル:ログインチェック(難易度 ⭐)
# ログインをシミュレート——正しいユーザー名かつ正しいパスワード
username_correct = True
password_correct = False
can_login = username_correct and password_correct
print(f"Login result: {can_login}") # False——パスワードが間違い
# さらに一層追加:アカウントがロックされていないこと
account_locked = True
can_login = username_correct and password_correct and not account_locked
print(f"Final result: {can_login}") # False——アカウントがロックされている
Output:
Login result: False
Final result: False
4. or:少なくとも一方が True
or は「いずれか」を意味します——少なくとも一方の条件が真なら結果は True です。両方とも偽のときだけ結果は False です。
| 左辺 | 右辺 | 結果 |
|---|---|---|
| True | True | True |
| True | False | True |
| False | True | True |
| False | False | False |
# 週末または祝日は休める
is_weekend = True
is_holiday = False
can_rest = is_weekend or is_holiday
print(can_rest) # True (週末だから)
# 地下鉄の保安検査:水または飲み物を持っていれば検査が必要
has_water = True
has_drink = False
need_check = has_water or has_drink
print(f"Security check needed: {need_check}") # True
(1) 練習:真理値表の完全な検証
# 真理値表をコードで検証——and と or の全組み合わせ
a = True
b = True
print(f"{a} and {b} = {a and b}")
print(f"{a} or {b} = {a or b}")
a = True
b = False
print(f"{a} and {b} = {a and b}")
print(f"{a} or {b} = {a or b}")
a = False
b = True
print(f"{a} and {b} = {a and b}")
print(f"{a} or {b} = {a or b}")
a = False
b = False
print(f"{a} and {b} = {a and b}")
print(f"{a} or {b} = {a or b}")
Output:
True and True = True
True or True = True
True and False = False
True or False = True
False and True = False
False or True = True
False and False = False
False or False = False
5. 短絡評価(ショートサーキット)
これはレッスン03でも触れましたが、非常に重要なのでさらに掘り下げます。Pythonの論理演算子は、結果が確定した時点で評価を即座に停止し、残りの式を実行しません。
(1) and の短絡:左辺が False → 右辺は実行されない
def check_right():
print("-> check_right was called!")
return True
print("False and check_right():")
result = False and check_right() # check_right は実行されない
print(f"Result: {result}\n")
print("True and check_right():")
result = True and check_right() # check_right は実行される
print(f"Result: {result}")
Output:
False and check_right():
Result: False
True and check_right():
-> check_right was called!
Result: True
(2) or の短絡:左辺が True → 右辺は実行されない
print("True or check_right():")
result = True or check_right() # check_right は実行されない
print(f"Result: {result}")
(3) 短絡評価の代表的な使い方
1. 安全なアクセス:None エラーの防止
# ユーザーが None の場合があると仮定(ユーザーが存在しない)
user = None
# user.get("name") はエラーになる——None には get メソッドがない
# 短絡を使って保護する:
name = user and user.get("name")
print(name) # None——user が偽なので短絡し、user.get() は呼ばれない
# ユーザーが存在する場合:
user = {"name": "Xiao Ming"}
name = user and user.get("name")
print(name) # Xiao Ming
2. デフォルト値の設定
# ユーザーが名前を入力しなかったらデフォルトを使う
user_input = "" # 空文字列(偽)
name = user_input or "guest"
print(f"Welcome, {name}") # Welcome, guest
user_input = "Zhang San"
name = user_input or "guest"
print(f"Welcome, {name}") # Welcome, Zhang San
ヒント:
user_input or "default"というパターンは非常にPythonらしい書き方です——左辺が偽(空文字列)なら右辺を使い、真(内容あり)なら左辺を使います。これはorの短絡の仕組みを利用しています。
6. 真の値と偽の値
Pythonでは、どんな値も条件の中でブール値として使えます。一部の値は「偽(falsy)」とみなされ、それ以外はすべて「真(truthy)」です。
(1) よくある偽の値
# これらの値は条件の中で False と同等
print(bool(False)) # False——ブール値の偽
print(bool(0)) # False——ゼロ
print(bool(0.0)) # False——浮動小数点のゼロ
print(bool("")) # False——空文字列
print(bool([])) # False——空リスト(後で扱う)
print(bool(None)) # False——null 値
それ以外はすべて真です:
print(bool(1)) # True——ゼロ以外の数
print(bool(-5)) # True——負の数も真!
print(bool("Python")) # True——空でない文字列
print(bool(" ")) # True——スペースは1文字で、空でなければ真
print(bool([1, 2])) # True——空でないリスト
警告:
-5と" "(スペース)はどちらも真であり、驚くかもしれません。-5はゼロ以外の整数なので真です。スペースは1文字なので文字列は空ではなく、真になります。空文字列""だけが偽です。
(2) 真偽性を利用してコードを簡潔にする
# 推奨しない(冗長)
name = "Xiao Ming"
if name != "":
print(f"Hello, {name}")
# 推奨する(簡潔)
name = "Xiao Ming"
if name:
print(f"Hello, {name}")
# 推奨しない
score = 85
if score != 0:
print(f"Score: {score}")
# 推奨する
score = 85
if score:
print(f"Score: {score}")
ヒント: 真偽性を活用するとコードがきれいになります。
if name:はif name != "":よりも「Pythonらしい」です。ただし使いすぎには注意してください——score=0のときif score:は実行されません。「スコアが0」と「スコアがない」を区別する必要がある場合は、is not Noneを使いましょう。
7. is と is not:同一性の比較
is は2つの変数が同じオブジェクト(メモリ上の同じ領域)を指しているかを比較し、値が等しいかは比較しません。これはレッスン03でも触れましたが、ここでさらに例を挙げて定着させます。
# == は値を比較し、is は同一性を比較する
a = [1, 2, 3]
b = [1, 2, 3]
c = a
print(a == b) # True——値は同じ
print(a is b) # False——しかし同じリストオブジェクトではない
print(a is c) # True——c は a であり、同じリストを指す
# 小さい整数のキャッシュ(Python内部の最適化)
x = 256
y = 256
print(x is y) # True かもしれない——小さい整数はキャッシュされる
x = 1000
y = 1000
print(x is y) # False かもしれない——大きい整数はキャッシュされない
警告: 整数や文字列を値で比較するために
isを使ってはいけません。 Python内部の最適化により小さい整数はisでTrueを返すことがありますが、これは実装の詳細であり信頼できません。値の比較には常に==を使いましょう。
(1) 正しい使い方:None のチェック
Python コミュニティには慣習があります——値が None かどうかをチェックするときは、常に is を使い、== は使いません:
# 正しい方法
result = None
if result is None:
print("No result")
# 推奨しない
if result == None:
print("No result")
▶ サンプル:登録条件の検証(難易度 ⭐⭐)
username = "alice2026"
password = "abc123"
age = 20
agreed_terms = True
is_valid = (
bool(username) and
len(password) >= 6 and
age >= 18 and
agreed_terms
)
reason = (
(not username and "Username is empty") or
(len(password) < 6 and "Password too short") or
(age < 18 and "Underage") or
(not agreed_terms and "Terms not agreed") or
"Registration successful"
)
print(f"Registration result: {is_valid}")
print(f"Reason: {reason}")
age = 16
is_valid2 = bool(username) and len(password) >= 6 and age >= 18 and agreed_terms
reason2 = (
(not username and "Username is empty") or
(len(password) < 6 and "Password too short") or
(age < 18 and "Underage") or
(not agreed_terms and "Terms not agreed") or
"Registration successful"
)
print(f"Registration result: {is_valid2}")
print(f"Reason: {reason2}")
Output:
Registration result: True
Reason: Registration successful
Registration result: False
Reason: Underage
8. よくあるユースケース
- 権限制御:
is_admin or (is_logged_in and has_permission)——複数の条件を組み合わせて、ユーザーが何をできるかを決めます。 - 入力検証:
username and password——ユーザーが両方入力したかチェックします。 - オプションパラメータのデフォルト:
timeout or 30——timeout が未設定ならデフォルトの30秒を使います。 - 安全なアクセスチェーン:
user and user.address and user.address.city——階層ごとの安全なアクセス。偽の段階で短絡します。 - トグル制御:
is_enabled and is_connected——操作を進めるには両方の条件を満たす必要があります。
❓ よくある質問
True と "True" の違いは何ですか?True(引用符なし)はブール値、"True"(引用符あり)は文字列です。両者は異なります。type(True) は <class 'bool'>、type("True") は <class 'str'> です。条件では、if "True": は常に True(空でない文字列は真)、if "False": も常に True(これも空でない)になります。したがって、条件の中でブール値に引用符を付けてはいけません。is と == はいつ使い分けるべきですか?== を使います。is が慣習として使われるのは1つの場面だけです——None のチェック(if result is None:)。その他の値の比較にはすべて == を使います。覚えておきましょう:== は「値」を比較し、is は「同一性」を比較します。and/or の短絡評価にはどんな落とし穴がありますか?and や or の右辺に関数呼び出しを置くと、短絡によって実行されず、スキップされたことに気づけない場合があります。その関数に副作用(ログ記録、メール送信、カウンタ更新)があると、短絡が原因で一貫性のない挙動を引き起こす可能性があります。良い習慣は、右辺の式に副作用がある場合、短絡に頼らず、別々に書くことです。not not "hello" が True を返すのはなぜですか?not "hello" はまず "hello" をブール値として評価し(空でない文字列は真)、否定して False を得ます。次に not not "hello" は False をもう一度否定して True を得ます。つまり not not x は bool(x)——x をブール値に変換すること——と同等です。ただしこのパターンは一般的ではないので、明確さのためには bool(x) を直接使いましょう。📖 まとめ
- ブール値は
TrueとFalseの2つだけです。これらはintのサブクラスですが(True=1、False=0)、算術には使いません notは否定します:真は偽に、偽は真になりますandは両方が真であることを要求しますorは少なくとも一方が真であることを要求します- Pythonの偽の値には
False、0、0.0、""、[]、Noneが含まれます——それ以外はすべて真です - 短絡:
andは左辺が偽なら右辺を実行せず、orは左辺が真なら右辺を実行しません - 短絡は「安全なアクセス」と「デフォルト値」という2つの代表的なパターンを可能にします
isは同一性を比較し、==は値を比較します。Noneのチェックにはisを使います
📝 練習問題
-
初級(難易度 ⭐):これらの式の値を予想し、検証してください:
not (10 > 5)True and False or Truenot False and True(5 > 3) or (2 > 10) and (8 == 8)— ヒント: 優先順位に注意——andはorより高い
-
中級(難易度 ⭐⭐):ユーザーの入力文字列を検証するコードを書いてください:
- 入力が空なら「Input cannot be empty」を出力
- 入力がすべてスペースなら、これも「Input cannot be empty」として扱う(ヒント:
strip()を使う) - 入力の長さが6未満なら「Input must be at least 6 characters」を出力
- それ以外は「Input is valid」を出力
-
上級(難易度 ⭐⭐⭐):「3桁の数のチェッカー」を書いてください。3桁の数
num(例:153)が与えられたとき、以下を判定します:- 偶数か?(
%を使う) - 3と5の両方で割り切れるか?
- 回文数か?(百の位と一の位が等しい。例:121、353)
- 上記の条件をいくつ満たすか?その数を出力します。
すべてのチェックにブール式だけを使い、if 文は使わないでください(それは次のレッスンに取っておきます)。
- 偶数か?(