Pythonではif文の条件式は真偽値に自動変換されます。
数値の0や空の文字列、空のリストがFalseになる一方、’0’や空白文字はTrueなど、初学者が驚く点も多いです。
この記事ではTruthiness(真偽値への変換)の仕組みを、bool()での確認方法や実行可能なサンプル付きで丁寧に解説します。
PythonのTruthiness(True/False判定)とifの基礎
ifの条件はboolに変換される
Pythonのif文は、条件式の値が必ず真偽値(bool)に変換されてから判定されます。
内部的にはbool(obj)
が呼ばれ、次のルールで決まります。
1つめはobj.__bool__()
があればその結果を使い、なければ2つめとしてobj.__len__()
があれば長さが0ならFalse、それ以外はTrueになります。
どちらもなければTrueです。
実務では仕組みを丸暗記する必要はありませんが、ifの条件は最終的にTrueかFalseにされることを覚えておくと、コードの挙動が読み解きやすくなります。
bool()で結果を確認する
挙動があいまいに感じるときは、bool()
で実際に評価結果を確かめるのが最速です。
例えばbool('0')
はTrue、bool('')
はFalseです。
注意: 文字列'False'
は文字数が非ゼロのためbool('False')
はTrueです。
サンプル(bool()の基本)
以下は代表的な値をbool()
で評価してみる例です。
# 基本的なbool()の挙動を確認するサンプル
values = [
None, False, 0, 0.0, 0+0j, # Noneやゼロ(整数・浮動小数・複素数)
"", b"", # 空の文字列・空のバイト列
[], (), {}, set(), range(0), # 空のコレクション
1, -1, 0.1, # 非ゼロの数値
"0", " ", "False", # 非空の文字列
[0], (0,), {"x": 0}, {0}, range(1), # 要素があるコレクション
]
for v in values:
# !r でrepr表現を表示し、空文字や空白の違いが分かるようにする
print(f"{v!r:>11} -> {bool(v)}")
None -> False
False -> False
0 -> False
0.0 -> False
0j -> False
'' -> False
b'' -> False
[] -> False
() -> False
{} -> False
set() -> False
range(0, 0) -> False
1 -> True
-1 -> True
0.1 -> True
'0' -> True
' ' -> True
'False' -> True
[0] -> True
(0,) -> True
{'x': 0} -> True
{0} -> True
range(0, 1) -> True
PythonのifでFalseになる値(falsy)一覧
Pythonでは「ゼロ」「空」「None」「False」がFalseになるのが基本です。
次の表で代表例を整理します。
値の種類 | 例 | boolの結果 |
---|---|---|
None | None | False |
ブール | False | False |
数値のゼロ | 0, 0.0, 0+0j | False |
空の文字列 | ” | False |
空のバイト列 | b” | False |
空のコレクション | [], (), {}, set(), range(0) | False |
NoneとFalse
None
は「値がない」を表す特別なオブジェクトで、bool(None)
はFalseです。
False
はブール値そのもので、もちろんFalseです。
None判定にはis
を使うのが定石です。
if x is None:
の形にしましょう。
数値の0 (0, 0.0)
整数0や浮動小数点0.0、複素数0+0jはいずれもFalseです。
-0.0
も数値的には0のためFalseになります。
補足として、標準ライブラリのdecimal.Decimal(0)
やfractions.Fraction(0, 1)
もFalseになります。
空の文字列 ” と空のバイト b”
長さ0の文字列''
やバイト列b''
はFalseです。
しかし'0'
や' '
(スペース1個)は長さが1のためTrueです。
空のコレクション ([], (), {}, set(), range(0))
長さ0のリスト[]
、タプル()
、辞書{}
、集合set()
、要素数0のレンジrange(0)
はFalseです。
長さが0かどうかが評価基準になっている点を意識すると覚えやすいです。
サンプル(bool()とifの動作)
falsy値はif条件でスキップされます。
実際の動作を見てみましょう。
# falsyの例はifで実行されず、truthyの例だけが実行されます
samples = {
"None": None,
"False": False,
"zero": 0,
"empty_str": "",
"empty_list": [],
"empty_dict": {},
"empty_set": set(),
"empty_range": range(0),
"nonzero": 42,
"nonempty_str": "ok",
"nonempty_list": [1],
}
for name, value in samples.items():
if value:
print(f"{name:>13}: True -> 実行されました")
else:
print(f"{name:>13}: False -> スキップされました")
None: False -> スキップされました
False: False -> スキップされました
zero: False -> スキップされました
empty_str: False -> スキップされました
empty_list: False -> スキップされました
empty_dict: False -> スキップされました
empty_set: False -> スキップされました
empty_range: False -> スキップされました
nonzero: True -> 実行されました
nonempty_str: True -> 実行されました
nonempty_list: True -> 実行されました
PythonのifでTrueになる値(truthy)の例
基本的にはゼロでも空でもNoneでもFalseでもないものはTrueです。
非ゼロの数値
1や-1、0.1などの非ゼロの数値はTrueです。
特殊な値としてfloat('nan')
も非ゼロ扱いでTrueになります。
非空の文字列
'0'
や'False'
など、見た目がFalseっぽくても非空ならTrueです。
スペースだけの' '
も長さ1なのでTrueです。
要素があるコレクション
リストやタプル、辞書、集合、長さが正のrange()
はTrueです。
サンプル(ifでの判定例)
実用的なifの使い方を示します。
空チェックやNoneチェックはPython流の書き方にすると読みやすくなります。
# 代表的なtruthy判定例
count = 3
text = "hello"
items = [0, 1, 2]
rng = range(5)
if count: # 非ゼロ -> True
print("countは非ゼロです")
if text: # 非空文字列 -> True
print("textは非空です")
if items: # 要素あり -> True
print("itemsには要素があります")
if rng: # range(5) は長さ5 -> True
print("rngは空ではありません")
countは非ゼロです
textは非空です
itemsには要素があります
rngは空ではありません
初心者がハマるポイントと書き方のコツ
‘0’ は文字列なのでTrueになる
'0'
は非空文字列なのでTrueです。
数字の0と混同しないよう注意しましょう。
# '0' は非空文字列 -> True、 0 は数値のゼロ -> False
print(bool('0')) # True
print(bool(0)) # False
if '0':
print("'0' はTrueとして扱われます")
True
False
'0' はTrueとして扱われます
空白だけの文字列 ‘ ‘ もTrue
スペース1個の' '
は長さ1なのでTrueです。
空かどうかを厳密に調べるならif s == ''
やif s.strip() == ''
など目的に合わせた比較を使います。
s1 = " "
s2 = ""
print(bool(s1)) # True (スペース1つ)
print(bool(s2)) # False (空文字)
# 空白のみを空として扱いたい場合
if s1.strip() == "":
print("s1は空白のみなので実質的に空とみなします")
True
False
s1は空白のみなので実質的に空とみなします
空のリストはFalseなので if not lst: が簡潔
空チェックはif not lst:
のように書くのがPython流です。
if len(lst) == 0:
より読みやすく、PEP 8的にも自然です。
def process(items):
# 空なら早期リターン(ガード節)
if not items: # 空リストやNoneなどもまとめてFalse扱い
print("itemsが空です。処理をスキップします。")
return
print(f"{len(items)}件の処理を開始します。")
process([]) # 空 -> False
process([1, 2, 3]) # 要素あり -> True
itemsが空です。処理をスキップします。
3件の処理を開始します。
Noneかどうかは if x is None を使う
None判定はis
を使うのが正解です。
==
比較はオーバーライドされうるため、安全性と明確さに欠けます。
x = None
y = 0
# 良い例
if x is None:
print("xはNoneです")
# 悪い例(避けたい): 値によっては==がTrueになるクラスも理論上ありうる
if y == None: # PEP 8違反、かつ誤りやすい
print("これは実行されません")
# Noneでないことを確かめる
if y is not None:
print("yはNoneではありません")
xはNoneです
yはNoneではありません
覚え方(ゼロ・空・None・FalseはFalse)
覚え方は「ゼロ・空・None・FalseはFalse、それ以外はTrue」です。
境界例に悩んだらbool(x)
で即確認するクセを付けましょう。
まとめ
Pythonのif条件はすべて真偽値に自動変換されるため、「ゼロ」「空」「None」「False」以外はTrueという原則を知っておくと読み書きが楽になります。
特に文字列の’0’や’ ‘がTrueになる点、空のコレクションはFalseになる点、None判定にはisを使う点は実務で頻出です。
挙動に迷ったときはbool()
で結果を可視化し、if not lstなどPythonicな書き方を習慣化すると、コードはより簡潔で意図が伝わりやすくなります。