7.

Python の制御構文|if・for・while・match とインデントの書き方

編集
この記事の要点
  • Python の制御構文は if / for / while / match の 4 つだけ
  • ブロックはインデントで表し、行末に : を付ける。波かっこは使わない
  • for回数ではなく「並んでいるものを順に取り出す」ための構文
  • Python 独自の for...else / while...else は「break しなかったとき」に実行される
  • 中身を後回しにしたいときは pass。空のブロックは構文エラーになる

制御構文の全体像

構文使う場面詳細
if / elif / else条件で処理を分ける条件分岐 (if文)
forリストなど並んだ要素を順に処理する繰り返し処理
while条件が成り立つ間くり返す繰り返し処理(while文)
match値の形で分岐する(Python 3.10 以降)本記事で紹介
break / continueループを抜ける / 次へ進む繰り返しの中断 (break) / 繰り返しのスキップ (continue)
try / except例外が起きたときの流れ例外処理

switchdo-while、C 言語風の for (i = 0; i < n; i++)存在しません。代わりに matchwhile True + breakfor i in range(n) を使います。

共通の書き方

score = 75

if score >= 80:            # 行末に : を付ける
    print("合格")            # ブロックはインデント 4 個
elif score >= 60:
    print("再試験")
else:
    print("不合格")

for name in ["田中", "鈴木"]:
    print(name)

n = 3
while n > 0:
    print(n)
    n -= 1

条件を ( ) で囲む必要はありません。囲んでも動きますが、Python では付けないのが普通です。

ネストと pass

for row in [[1, 2], [3, 4]]:
    for value in row:
        if value % 2 == 0:
            print(value, "は偶数")

# 中身が未定のときは pass を置く(空行だとエラー)
def todo():
    pass

if False:
    pass          # あとで書く

ループの else 節

Python 独自の構文です。ループが break されずに最後まで回った場合だけ else が実行されます。「見つからなかったとき」の処理を素直に書けます。

users = ["田中", "鈴木"]

for u in users:
    if u == "佐藤":
        print("見つかった")
        break
else:
    print("見つからなかった")    # break しなかったのでここが動く

n = 0
while n < 3:
    n += 1
else:
    print("最後まで回った")      # 3

「else = 条件が偽のとき」ではない点に注意してください。break されなかったときと覚えます。

match 文(Python 3.10 以降)

def describe(command):
    match command:
        case "start":
            return "開始します"
        case "stop" | "halt":            # 複数候補は |
            return "停止します"
        case ["move", x, y]:             # リストの形で分解できる
            return f"({x}, {y}) へ移動"
        case {"type": "user", "name": name}:   # 辞書の形でも
            return f"ユーザー {name}"
        case int() as n if n > 0:         # 型と追加条件
            return f"正の数 {n}"
        case _:                          # どれにも当たらない場合
            return "不明"

print(describe(["move", 1, 2]))   # (1, 2) へ移動

match は単なる値の一致ではなく構造の分解ができるのが特徴です。値を比べるだけなら if/elif や辞書引きのほうが読みやすい場合もあります。

内包表記で置き換えられる場合

nums = [1, 2, 3, 4, 5]

# for でリストを作る書き方
result = []
for n in nums:
    if n % 2 == 0:
        result.append(n * 10)

# 内包表記なら 1 行
result = [n * 10 for n in nums if n % 2 == 0]    # [20, 40]

# 辞書・集合も同じ形で作れる
squares = {n: n * n for n in nums}
evens = {n for n in nums if n % 2 == 0}

「リストを作るためだけのループ」は内包表記にすると意図が伝わります。ただし条件が 2 つ以上になったり副作用がある場合は、素直に for で書いたほうが読みやすいです。

流れを変える 5 つのキーワード

キーワード何が起きるか置ける場所
breakいま入っているループを 1 段だけ抜けるfor / while の中
continue本体の残りを飛ばして次の周回へfor / while の中
return関数そのものを抜ける(多重ループも一気に抜ける関数の中
raise例外を投げて呼び出し元へ飛ばすどこでも
pass何もしない。ブロックを空にできない場所の穴埋めどこでも
def find_first_negative(matrix):
    for row in matrix:
        for v in row:
            if v < 0:
                return v          # 二重ループを一度に抜けられる
    return None

print(find_first_negative([[1, 2], [3, -4]]))   # -4

break内側の 1 段しか抜けません。多重ループから脱出したいときは、関数に切り出して return するのが最も読みやすくなります。

条件の中で代入する(セイウチ演算子)

# 計算結果を条件にも本体にも使いたい
data = [1, 2, 3, 4, 5]

if (n := len(data)) > 3:
    print(f"{n} 件あります")        # 5 件あります

# 読み込みループが 1 行にまとまる
with open("data.txt", encoding="utf-8") as f:
    while (line := f.readline()):
        print(line.rstrip())

# 内包表記で同じ計算を 2 回しない
values = [y for x in data if (y := x * 10) > 20]   # [30, 40, 50]

Python 3.8 で入った :=値を返しながら代入します。普通の = は式ではないため if n = len(data): とは書けません。多用すると読みにくくなるので、同じ計算を 2 回書かずに済む場面だけに使います。

後始末を保証する with 文

# ファイルは閉じ忘れがちなので with を使う
with open("data.txt", encoding="utf-8") as f:
    for line in f:
        print(line.rstrip())
# ここに来た時点で必ず閉じられている(途中で例外が出ても)

# 複数まとめて開く
with open("in.txt") as src, open("out.txt", "w") as dst:
    dst.write(src.read())

with は「ブロックを抜けるときに必ず何かをする」構文です。ファイル・DB 接続・ロックなど、開いたら必ず閉じるものに使います。

よく出る構文エラー

エラー原因
SyntaxError: expected ':'if / for / def の行末に : が無い
IndentationError: expected an indented block: の次の行をインデントしていない
SyntaxError: invalid syntaxかっこの閉じ忘れ。指摘された行の 1 つ前を見る
SyntaxError: 'break' outside loopループの外に break を書いている
TabErrorタブとスペースの混在

関連

編集
Post Share
子ページ
  1. 条件分岐 (if文)
  2. 繰り返し処理(while文)
  3. 繰り返し処理
  4. 繰り返しの中断 (break)
  5. 繰り返しのスキップ (continue)
同階層のページ
  1. 基本的なルール
  2. 変数
  3. 演算子
  4. 標準ライブラリ
  5. 外部ライブラリ
  6. 制御構文
  7. リスト(配列)
  8. タプル
  9. セット
  10. 辞書(dict)
  11. クラスとメソッド
  12. 継承の概念と必要性
  13. 継承の構文
  14. コンストラクタ
  15. cookieの値の設定と取得
  16. 例外処理
  17. 例外を文字列で出力する方法
  18. httpリクエスト(curl)をする方法
  19. Responseオブジェクトの中身の確認
  20. 変数が空かどうか判定する方法
  21. タイムゾーンの設定と現在日時の取得と文字列化
  22. シングルクォーテーションとダブルクォーテーションの違い

最近更新/作成されたページ