0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Python文法講義~制御構文~

Last updated at Posted at 2025-09-28

まえがき

今回は制御構文、具体的には、if, match, for, while, 例外処理について扱う。ただし、どの本にも書いてあるような構造については、深く扱うようなことはしない。その代わり、match 文を使うべき場面など、あまり書籍には取り上げられない項目については、掘り下げ気味に扱う。

if

構造 構文 特徴
単純分岐 if 条件: 条件が True のときだけ処理 if x>0:
二分岐 if ... else True なら処理1、False なら処理2 正負判定
多岐分岐 if ... elif ... else 条件を順に判定、最初の True の処理だけ実行 評価判定
ネスト if の中に if 条件を段階的に分岐 複合条件

単純分岐( if )

基本構文
if 条件式:
    処理

条件式が True の場合のみ処理が実行されるが、False の場合は何も実行されない。

x = 10
if x > 0:
    print("xは正の数です")
# 出力: xは正の数です

単純分岐( if-else )

基本構文
if 条件式:
    処理1
else:
    処理2

条件式が True の場合は 処理1 が実行されるが、False の場合は 処理2 が実行される。

x = -5
if x > 0:
    print("xは正の数です")
else:
    print("xは正の数ではありません")
# 出力: xは正の数ではありません

多岐分岐( if-elif-else )

基本構文
if 条件式:
    処理1
else:
    処理2

上から順に評価され、最初に True になった条件の処理が実行される。どの条件も満たさなければ else が実行される。

score = 75

if score >= 90:
    print("評価: A")
elif score >= 70:
    print("評価: B")
elif score >= 50:
    print("評価: C")
else:
    print("評価: D")

# 出力: 評価: B

ネスト構造の分岐(入れ子の if )

基本構文
if 条件1:
    if 条件2:
        処理1
    else:
        処理2
else:
    処理3

if 文の中にさらに if 文を入れることで、条件を細分化できる。条件が複雑になる場合は可読性が下がるため、論理演算子(and, or, not)を使う方が推奨されることも多い。

x = 10
y = -5

if x > 0:
    if y > 0:
        print("xもyも正の数です")
    else:
        print("xは正の数ですがyは正の数ではありません")
else:
    print("xは正の数ではありません")

# 出力: xは正の数ですがyは正の数ではありません

条件式を指定する際の注意点

注意点 説明 推奨方法
真理値評価 空の値は False、それ以外は True if not list: など
== vs is 等価性と同一性の違い 値比較は ==、None判定は is None
比較演算子チェーン 0 < x < 10 と書ける 可読性に注意
短絡評価 左が確定すれば右を評価しない 副作用ある式を注意して書く
None 判定 == None は避ける is None
包含判定 コレクションに要素が含まれるか "x in list"
浮動小数点比較 誤差があるため直接比較不可 math.isclose()

match ... case

基本概要

match 文:Pythonにおける構造的パターンマッチング機能
→ 他言語の swich-case と同様といわれることも多いが、値の比較にとどまらず、構造分解や型判定も可能

基本構文
match :
    case パターン1:
        処理1
    case パターン2:
        処理2
    case _:
        デフォルト処理

使用例は以下。

command = "start"

match command:
    case "start":
        print("処理を開始します")
    case "stop":
        print("処理を停止します")
    case _:
        print("未知のコマンドです")

# 処理を開始します

case _:はワイルドカードを示す。(どの条件も当てはまらなかった場合)

match 文を使うべき場面

[3] には以下のような節がある。
Item 9: Consider match for Destructuring in Flow Control; Avoid When if Statements Are Sufficient.
すなわち、「構造的パターンマッチングの場合には、match 文の使用を考えて、そもそも if 文の使用で事足りるなら、 match 文は避けるべき。」という記述である。

個人的に感じるmatch 文の使いどころは以下の3種類
・ 条件が複雑/多岐にわたる場合
・ 構造的パターンマッチング
・ 型ごとの処理

逆にこれらのいずれも満たさない場合は、if 文で充分であるし、match 文を用いる必要はないと感じる。

今回は技術ブログであるし、経度緯度の例をサラッと扱って終わるようなテキストがほとんどのため、一応ある程度網羅的に扱う。

1. リテラルパターン

→ 数値や文字列、None などのリテラル値と一致するとマッチする

def literal_demo(x):
    match x:
        case 0:
            return "zero"
        case "yes":
            return "affirmative"
        case None:
            return "is None"
        case _:
            return "other"

print(literal_demo(0))
print(literal_demo("yes"))
print(literal_demo(None))
print(literal_demo(42))
実行結果
zero
affirmative
is None
other

2. ワイルドカードパターン

_ はどんな値にもマッチし、変数としては束縛しない

def wildcard_demo(x):
    match x:
        case _:
            return "always matches"

print(wildcard_demo("anything"))
実行結果
always matches

3. キャプチャパターン

→ 値を新しい変数に束縛する。常にマッチする。

def capture_demo(x):
    match x:
        case y:
            return f"captured: {y}"

print(capture_demo([1, 2, 3]))
実行結果
captured: [1, 2, 3]

4. 値パターン

→ ドット参照を用いると、変数でなく既存の定数や属性と比較できる。

import math

def value_demo(x):
    match x:
        case math.pi:
            return "exactly math.pi"
        case math.e:
            return "exactly math.e"
        case _:
            return "other"

print(value_demo(math.pi))
print(value_demo(math.e))
print(value_demo(3.14159))
実行結果
exactly math.pi
exactly math.e
other

5. グループパターン

() でパターンをまとめて、優先順位を明示する

def group_demo(x):
    match x:
        case ("ok" | "yes") | ("y" | "1"):
            return "affirmative"
        case _:
            return "other"

print(group_demo("y"))
print(group_demo("no"))
実行結果
affirmative
other

6. シーケンスパターン

→ リストやタプルなどのシーケンスを分解できる。*rest で残りを受け取ることが出来る。

def sequence_demo(seq):
    match seq:
        case [x, y]:
            return f"pair: {x}, {y}"
        case [head, *middle, tail]:
            return f"head={head}, middle={middle}, tail={tail}"
        case []:
            return "empty"
        case _:
            return "other"

print(sequence_demo([10, 20]))
print(sequence_demo((1, 2, 3, 4)))
print(sequence_demo([]))

7. マッピングパターン

→ 辞書のキーと値をパターンとして指定可能。**rest で残りを受け取ることが出来る。

def mapping_demo(d):
    match d:
        case {"type": "user", "id": uid, "name": name, **rest}:
            return f"user id={uid}, name={name}, rest={rest}"
        case {"type": "system"}:
            return "system object"
        case _:
            return "unknown"

print(mapping_demo({"type": "user", "id": 7, "name": "Taro", "role": "admin"}))
print(mapping_demo({"type": "system", "uptime": 123}))
実行結果
user id=7, name=Taro, rest={'role': 'admin'}
system object

8. クラスポジショナル/キーワードパターン

→ データクラスやクラスの属性を分解できる。

from dataclasses import dataclass

@dataclass
class Point:
    x: int
    y: int

def class_demo(obj):
    match obj:
        case Point(0, 0):
            return "origin"
        case Point(x, 0):
            return f"on X axis at {x}"
        case Point(x=0, y=y):
            return f"on Y axis at {y}"
        case Point(x, y):
            return f"point({x}, {y})"
        case _:
            return "not a Point"

print(class_demo(Point(0, 0)))
print(class_demo(Point(5, 0)))
print(class_demo(Point(0, -2)))
print(class_demo(Point(3, 4)))
origin
on X axis at 5
on Y axis at -2
point(3, 4)

9. or パターン

| で複数のパターンのいずれかにマッチする。

def or_demo(x):
    match x:
        case 0 | 0.0 | False:
            return "falsy zero"
        case "y" | "yes" | "ok":
            return "affirmative"
        case _:
            return "other"

print(or_demo(0.0))
print(or_demo("ok"))
print(or_demo(2))
実行結果
falsy zero
affirmative
other

10. as パターン

→ 部分パターンにマッチしつつ、全体を変数に束縛する

def as_demo(obj):
    match obj:
        case {"type": "user", "id": uid} as whole:
            return f"user #{uid}, whole={whole}"
        case Point(x, y) as p:
            return f"Point captured: {p} (x={x}, y={y})"
        case _:
            return "no match"

print(as_demo({"type": "user", "id": 99, "name": "Ai"}))
print(as_demo(Point(1, 2)))
実行結果
user #99, whole={'type': 'user', 'id': 99, 'name': 'Ai'}
Point captured: Point(x=1, y=2) (x=1, y=2)

上記の1~10のうち、どのケースで match 文を用いるべきかを明記する。基本的に、7のマッピングパターンを除き(他には1、2、6、8も許容可能に感じる)、代替可能なので、書けるのであれば if 文で書くべきである。しかし、条件分岐が多量多岐に渡る場合は、match 文でも代用に値する。

while

基本概念

while 条件式:
    実行する処理
else:
    条件式が偽になって正常終了したときに実行する処理任意

条件式が True の間、ブロック内の処理を繰り返し、条件式が False となるとループを終了。else 節は break で抜けなかった場合に実行される。

count = 0
while count < 3:
    print("count:", count)
    count += 1
else:
    print("正常終了")
実行結果
count: 0
count: 1
count: 2
正常終了

while 文と制御構文

break による中断

→ ループを強制終了する。else 節はスキップされる。

n = 0
while n < 5:
    if n == 3:
        break
    print(n)
    n += 1
else:
    print("正常終了")
実行結果
0
1
2

continue によるスキップ

→ 残った処理をスキップして、次のループに移る。

n = 0
while n < 5:
    n += 1
    if n % 2 == 0:
        continue
    print(n)
1
3
5

ネストされた while

→ 入れ子構造も可能。この場合、外側/内側でカウンタを管理する必要がある。

i = 1
while i <= 3:
    j = 1
    while j <= 2:
        print(f"i={i}, j={j}")
        j += 1
    i += 1
実行結果
i=1, j=1
i=1, j=2
i=2, j=1
i=2, j=2
i=3, j=1
i=3, j=2

これを応用して、以下のように素数を検索するコードも書ける。

n = 2
while n < 20:
    is_prime = True
    i = 2
    while i < n:
        if n % i == 0:
            is_prime = False
            break
        i += 1
    if is_prime:
        print(n, "は素数")
    n += 1
実行結果
2 は素数
3 は素数
5 は素数
7 は素数
11 は素数
13 は素数
17 は素数
19 は素数

while True: による条件の後判定

基本的な構文は以下。

while True:
    # ループ処理
    print("必ず1回は実行される")
    
    # 条件判定(Falseならループを抜ける)
    if not 条件式:
        break

具体例は以下。

n = 1
while True:
    print(n)
    n *= 2
    if n > 100:
        break
実行結果
1
2
4
8
16
32
64
128

for

for 文の基本構造

基本構造は以下。

基本構造
for 変数 in iterable:
    実行する処理
else:
    breakされずに終了したときに実行する処理任意

基本例は以下。

for i in range(3):
    print("i:", i)
else:
    print("正常終了")
実行結果
i: 0
i: 1
i: 2
正常終了

for 文の便利な組み合わせ

enumerate

→ インデックスと要素を同時に取り出す

words = ["a", "b", "c"]
for idx, w in enumerate(words, start=1):
    print(idx, w)
実行結果
1 a
2 b
3 c

zip

→ 複数のイテラブルを並列に処理

names = ["A", "B", "C"]
scores = [90, 80, 70]
for n, s in zip(names, scores):
    print(n, s)
実行結果
A 90
B 80
C 70

dict のループ

d = {"x": 1, "y": 2}
for key, value in d.items():
    print(key, value)
実行結果
x 1
y 2

ネストされた for

for i in range(1, 10):
    for j in range(1, 10):
        print(f"{i*j:2}", end=" ")
    print()
実行結果
 1  2  3  4  5  6  7  8  9
 2  4  6  8 10 12 14 16 18
 ...

フラグ変数によるループの脱出

for/while-else の代わりに、フラグ変数を用いて脱出することも可能。

nums = [1, 3, 5, 7, 9]
flag = False

for n in nums:
    if n % 2 == 0:   # 偶数を発見したら
        flag = True
        break

if flag:
    print("偶数が見つかりました")
else:
    print("偶数は存在しません")
実行結果
偶数は存在しません

例外処理

今回は例外処理について扱う。

例えばアプリ開発において、様々なエラーに直面するが、このうち事前対処が可能か不可能かによって大別できる。
→ 対処可能:(いわゆる)構文エラー、対処不可能:例外

後者の例外を、例外処理にて対処することになる。

基本的な構文を先にあげておく

基本構文
try:
    # 例外が発生する可能性のある処理
except エラー型 as 変数:
    # 例外が発生した場合の処理
else:
    # 例外が発生しなかった場合の処理
finally:
    # 例外の有無にかかわらず必ず実行される処理

例外を処理するー try

例外処理:あらかじめ発生するかもしれないエラーを想定しておき、実行を継続するため/安全に終了ための処理

最もシンプルなのは、try-except 命令

try:
    # 例外が発生する可能性のある処理
except エラーの種類:
    # 例外が発生したときの処理

try ブロックで例外が起きると、そこで処理が中断し except ブロックに移行。ただし、except に指定しなかった例外は処理できずそのまま送出される。

具体例は以下。以下のように、except を複数書くことで、例外ごとに異なる処理が可能。

try:
    value = int("abc")
except ValueError:
    print("数値に変換できません")
except TypeError:
    print("型が不正です")

else 節は、例外が発生しなかった場合に実行される。正常系とエラー形を分離できるので、可読性が向上する。

try:
    value = int("123")
except ValueError:
    print("変換失敗")
else:
    print("変換成功:", value)

finally は、例外の有無にかかわらず実行れさ、ファイルやネットワーク接続などのリソース解法に用いられる。

try:
    f = open("sample.txt", "r")
    data = f.read()
except FileNotFoundError:
    print("ファイルが存在しません")
finally:
    print("必ず実行される処理")
    if 'f' in locals() and not f.closed:
        f.close()

raise で明示的に例外を送出できる。条件違反や入力不正の建設に利用できる。

def divide(a, b):
    if b == 0:
        raise ZeroDivisionError("0で割ることはできません")
    return a / b

raise とだけ書くと、補足した例外を再度送出する。ログを記録してから上位に伝えるなどの使い方ができる。

Exception を継承したクラスを作成し、アプリケーション固有のエラー処理を実現できる。

class CustomError(Exception):
    pass

try:
    raise CustomError("独自エラーです")
except CustomError as e:
    print("捕捉:", e)

まとめ

実行される条件
try 常に実行される
except 指定例外が発生したとき
else 例外が発生しなかったとき
finally 常に実行される(終了処理に必須)

参考文献

[1] 独習Python 第2版 (2025, 山田祥寛, 翔泳社)
[2] Pythonクイックリファレンス 第4版(2024, Alex, O’Reilly Japan)
[3] Effective Python: 125 Specific Ways to Write Better Python, 3rd Edition (2025, Brett Slatkin, O’Reilly)

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?