2.11. 条件分岐

条件分岐 は、あるテストが真と評価された場合にのみコードブロックを実行します。キーワードは if で、オプションで1つ以上の elif(「else if」)分岐と最後の else を続けられます。

n = 42

if n > 0:
    print("positive")
elif n < 0:
    print("negative")
else:
    print("zero")

各分岐の本体は、その下にインデントされたすべて(慣習として4つのスペース)です。Pythonは分岐を順に巡り、テストが真である最初のものを実行し、残りをスキップします。else ブロックは、それ以前のすべてのテストが偽だった場合にのみ実行され、常にオプションです。

if/elif/else を示すフローチャート。2つのひし形の判定 テストとそれぞれの本体があり、両方のテストが偽のときは 最後の else 本体へ落ちる。

実行される分岐は常に1つだけです。テストは上から下へ、1つが成功するまで評価され、残りはスキップされます。

2.11.1. 真偽値性

if 内のテストは TrueFalse を返す必要はありません。任意の値が 真値 または 偽値 のいずれかとして扱われます。偽値は次のとおりです:

  • FalseNone

  • 数値のゼロ: 00.0

  • 空のシーケンスとコレクション: ""[](){}b""

それ以外はすべて真値です。これによりコンパクトなテストを書けます:

if name:                     # false on empty string
    print("hello", name)

if items:                    # false on empty list, dict, etc.
    process(items)

真偽値性が意味を変えることに注意してください。if value:if value is not None:同じではありません。前者は value0"" の場合にも偽になります。本当に「これがちょうど None か」を意味したい場合は、is None / is not None を明示的に使ってください。

2.11.2. 三項式

条件分岐は式の中にも現れます:

label = "even" if n % 2 == 0 else "odd"

n % 2 == 0 なら label"even"そうでなければ "odd"」と読みます。ワンライナーには便利ですが、1行を超えるものには完全な if 文のほうが読みやすいです。

2.11.3. ネストと早期リターン

条件分岐は任意の深さにネストできますが、インデントの層が1つ増えるごとに関数は読みにくくなります。下の例は、本当の処理を行う前に4つの条件をチェックし、有用な行を4段のインデントの奥深くに埋もれさせています:

def process(item):
    if item is not None:
        if item.is_valid():
            if item.size() > 0:
                if item.owner == "me":
                    return do_the_work(item)
    return None

この種のコードを平坦にする2つのパターンがあります。

2.11.3.1. ガードのための早期リターン

すべての「離脱」ケースをそれぞれ独自の return で最初に処理することで、メインのロジックを外側のインデントに保ちます。各ガードは「これは扱うケースではないので離れる」と読めます:

def process(item):
    if item is None:
        return None
    if not item.is_valid():
        return None
    if item.size() == 0:
        return None
    if item.owner != "me":
        return None
    return do_the_work(item)

「メインの経路」が、4層の内部に埋もれるのではなく、関数の末尾の1行になりました。このスタイルは ガード節 パターンと呼ばれることがあります。

2.11.3.2. and / or でのテストの結合

同じ分岐に対して複数の条件がすべて成り立つ必要がある場合は、ネストするのではなく and で結合します。それぞれが独立してその分岐を起動する条件は or で結合します:

# all must hold -- use `and`
if user.is_admin() and user.has_permission("write") and not locked:
    save()

# any one of them is enough -- use `or`
if c == " " or c == "\t" or c == "\n":
    whitespace_count += 1

どちらの形式も短絡評価されるため、右側のコストの高いチェックは、左側のより安価なチェックでまだ決着がついていない場合にのみ実行されます。