PC-LABOを試すためのPython入門(第2回)~条件分岐・ループ・関数の引数・辞書~

Python

このシリーズについて

このブログでは、「基本情報技術者試験問題に挑戦しよう!」シリーズをはじめ、Pythonの短いプログラムを動かしながら仕組みを確かめる記事を多く扱っている。

このシリーズでは、「このブログのコードを読める・動かせるようになる」ことを目標に、Pythonの基礎を3回に分けて学んでいこう。

  • 第1回:変数・型・print
  • 第2回(今回):条件分岐・ループ・関数の引数・辞書
  • 第3回:クラスと標準ライブラリの読み方

Windowsを利用する場合、今回のコードも、第1回で説明した通り、py とだけ打ってPythonの対話モードに入るのではなく、ファイル名.py として保存してから、PowerShellから直接 py ファイル名.py の形で実行してほしい。

なお、この記事で使用するコードは、筆者の学習用リポジトリ pc-labo-python-basic の 02_if_for_function_dict フォルダにまとめている。

条件分岐(if / elif / else)

条件分岐とは、「条件によって処理を変える」仕組みである。Pythonでは if / elif(else ifの意味)/ else を使う。

score = 82

if score >= 90:
    print("S判定")
elif score >= 80:
    print("A判定")
else:
    print("B判定以下")

実行結果

A判定

if の条件が成り立たなければ次の elif を調べ、それも成り立たなければ else の処理が実行される。上から順に条件をチェックし、最初に成り立った条件のところだけが実行される点がポイントである。

ところで、Pythonでは、if の後ろに書いたブロックをインデント(字下げ、通常は半角スペース4つ)で表す。C言語などにある { } は使わず、インデントの深さそのものが「どこまでがこのブロックか」を表す。
このインデントは、見た目を整えるためではなく、Pythonの文法そのものである。
インデントがずれると、意図しない動きをしたりエラーになったりするので注意したい。
次の例は、誤りのコードである。

# --- エラーの例 ---
score = 82

if score >= 90:
print("S判定")
elif score >= 80:
print("A判定")
else:
print("B判定以下")


実行すると、次のような IndentationError になる。

PS C:\python> py .\err.py
  File "C:\python\err.py", line 5
    print("S判定")
    ^^^^^
IndentationError: expected an indented block after 'if' statement on line 4

このエラーメッセージは「if 文(4行目)の後ろに、インデントされたブロックがあるはずなのに見つからない」という意味である。if score >= 90: の次の行(print("S判定"))が、正しくインデントされていないと発生する。

※本記事からコードをコピーする際、環境によっては HTMLタグ<br> が混入して行がつながることがある。コードを実行する前に、各行が正しく改行されているか確認してほしい。

ループ(for, range)

ループとは、同じ処理を繰り返す仕組みである。Pythonでは主に for 文を使う。

for i in range(3):
    print(f"{i}回目")

実行結果

0回目
1回目
2回目

range(3) は、0, 1, 2という3つの数を順番に生成する。
Pythonの数え方は0から始まる点に注意したい。

for はリストの中身を1つずつ取り出す使い方もよくする。

fruits = ["りんご", "みかん", "ぶどう"]
for fruit in fruits:
    print(fruit)

実行結果

りんご
みかん
ぶどう

本ブログの基本情報技術者試験問題シリーズでは、for n in [1, 5, 100, 127]: のように、確認したい値をリストにまとめて for で1つずつ処理する書き方が出ている。

辞書(dict)

辞書とは、「キー」と「値」の組をまとめて管理するデータ構造である。
リストでは要素を位置(インデックス)で扱うのに対し、辞書ではキーを使って値を取り出す。

port_names = {80: "HTTP", 443: "HTTPS", 21: "FTP"}
print(port_names[80])
print(port_names.get(8080, "登録なし"))

実行結果

HTTP
登録なし

辞書名[キー] で値を取り出せるが、存在しないキーを指定するとエラーになる。.get(キー, 見つからなかった場合の値) を使うと、キーが無い場合にエラーにせず、指定した値を返してくれる。

辞書のすべての組を順番に取り出すには、.items() を使う。

以下は、直前のブロックで定義した port_names に続けて記述する抜粋である。単独で実行すると NameError になるので、直前のブロックに続けて1つのファイルに書いてほしい。

# (抜粋:直前のport_namesに続けて記述する)
for port, name in port_names.items():
    print(f"{port}番 -> {name}")

実行結果

80番 -> HTTP
443番 -> HTTPS
21番 -> FTP

辞書は、「ポート番号とサービス名の対応」のような、組になったデータを扱うときに便利である。

関数の引数(複数引数・デフォルト引数)

第1回でも関数を扱ったが、関数には複数の引数を渡すことができ、さらにデフォルト引数(呼び出し時に省略できる引数)を設定できる。

def rank(score, passing_score=60):
    """点数からランクを返す(合格ラインはデフォルト60点)"""
    if score < passing_score:
        return "不合格"
    elif score >= 90:
        return "S"
    elif score >= 80:
        return "A"
    else:
        return "B"


print(rank(85))
print(rank(55))
print(rank(55, passing_score=50))  # 合格ラインを50点に変更

実行結果

A
不合格
B

rank(85) のように passing_score を省略すると、関数定義のときに指定した初期値(60)がそのまま使われる。rank(55, passing_score=50) のように明示的に指定すると、その値で上書きされる。このブログのFE記事でも、def two_complement(n, bits=8): のように、通常はそのままでよいが必要なら変更できる値を、デフォルト引数として用意しているコードがよく出てくる。

【つくってみよう】得点からランク判定+集計プログラム

ここまでの内容(if・for・辞書・関数の引数)を組み合わせて、複数人の得点からランクを判定し、ランクごとの人数を集計するプログラムを作ってみよう。

def rank(score, passing_score=60):
    """点数からランクを返す(合格ラインはデフォルト60点)"""
    if score < passing_score:
        return "不合格"
    elif score >= 90:
        return "S"
    elif score >= 80:
        return "A"
    else:
        return "B"


scores = [95, 82, 67, 40, 73]
counts = {}  # ランクごとの人数を数える辞書

print("=== 各生徒の判定 ===")
for s in scores:
    r = rank(s)
    print(f"{s:3d}点 -> {r}")
    counts[r] = counts.get(r, 0) + 1  # そのランクの人数を1増やす

print()
print("=== ランク別人数 ===")
for r, count in counts.items():
    print(f"{r}: {count}人")

実行結果

=== 各生徒の判定 ===
 95点 -> S
 82点 -> A
 67点 -> B
 40点 -> 不合格
 73点 -> B

=== ランク別人数 ===
S: 1人
A: 1人
B: 2人
不合格: 1人

counts[r] = counts.get(r, 0) + 1 の部分が、集計の核心である。counts.get(r, 0) で「そのランクがまだ辞書に無ければ0」を取得し、それに1を足して、あらためて counts[r] に代入している。これにより、辞書に無いキーへのアクセスでエラーになることなく、ランクごとの人数を数え上げられる。

なお、このコードは1つのファイルとして完結しているので、そのままコピーして保存し、py ファイル名.py で実行できる。

まとめ

  • if / elif / else で、条件によって処理を分けられる。ブロックはインデントで表す
  • for と range() を組み合わせると、決まった回数の繰り返しができる。リストと組み合わせれば、中身を1つずつ処理できる
  • 辞書(dict)は、キーと値の組でデータを管理する。.get() を使うと、キーが無い場合にもエラーにせず処理できる
  • 関数にはデフォルト引数を設定でき、呼び出し側で省略した場合に使われる初期値を用意できる

今回学んだ条件分岐・ループ・辞書・デフォルト引数が読めれば、「命題の真理値」「システムの稼働率」「回線の伝送時間」などのFE記事のコードが、かなり読みやすくなっているはずである。

次回は、クラスの基本(class, __init__, self)と、このブログでよく出てくる標準ライブラリの読み方を扱う。

(参考)筆者のリポジトリ

この記事で扱ったコードは、以下の筆者のGitHubリポジトリで公開している。

GitHub – HappyTalk10/pc-labo-python-basic
Contribute to HappyTalk10/pc-labo-python-basic development by creating an account on GitHub.
タイトルとURLをコピーしました