2  Python で処理を組み立てる

チャプター 1 では,変数やリストを使った計算と,関数の呼び出しを学んだ.本章では,条件分岐と繰り返しを使って処理の流れを組み立て,自分で関数を定義する方法を学ぶ.さらに,モジュールを読み込み,既存の機能を利用する方法を扱う.

これらを組み合わせたコードを理解し,目的に合わせて書き換えられるようになることを目指す.

2.1 条件分岐

条件に応じて処理を分けるには,if 文を使う.次のコードでは,x が 0 より大きければ「正の数」,そうでなければ「正の数ではない」と表示する.

x = 10

if x > 0:
    print("正の数")
else:
    print("正の数ではない")
正の数

if の後ろに条件を書き,行末に : を付ける.次の行からは,行の先頭に空白を入れて,処理を書く位置を右にずらす.これを「インデント(字下げ)」という.

条件が成り立つときは,if の下にインデントして書いた処理が実行される.条件が成り立たないときは,else の下にインデントして書いた処理が実行される.

Python では,インデントによって処理のまとまりを表す.同じまとまりに属する行は,インデントをそろえる必要がある.通常は,インデントを 1 段深くするごとに半角スペースを 4 つ使う.

値を比較する条件を書くには,次の比較演算子を使う.比較の結果は,条件が成り立つときは True,成り立たないときは False になる.

演算子 意味 例 結果
== 等しい 3 == 3 True
!= 等しくない 3 != 3 False
< より小さい 3 < 5 True
<= 以下 3 <= 3 True
> より大きい 3 > 5 False
>= 以上 3 >= 3 True

= は値の代入に使い,== は値が等しいかどうかの比較に使う.

if の条件が成り立たないときに,別の条件を調べるには,elif を使う.条件は上から順に調べられ,最初に成り立った条件に対応する処理だけが実行される.どの条件も成り立たない場合は,else の処理が実行される.else は省略することもできる.

if と elif を使うと,数が正,零,負のいずれであるかを判定できる.

x = 0

if x > 0:
    print("正の数")
elif x == 0:
    print("零")
else:
    print("負の数")
零

まず,x > 0 かどうかを調べる.この条件が成り立たない場合は,次に x == 0 かどうかを調べる.どちらも成り立たない場合は,else の処理が実行される.

図 2.1 に,この判定の流れを示す.いずれか一つの表示を行うと,条件分岐の後の処理へ進む.

%%{init: {"theme": "neutral", "flowchart": {"rankSpacing": 30, "nodeSpacing": 30}}}%%
flowchart TD
    A{"x > 0"} -->|True| B["「正の数」を表示"]
    A -->|False| C{"x == 0"}
    C -->|True| D["「零」を表示"]
    C -->|False| E["「負の数」を表示"]
    B --> F["条件分岐の後の処理"]
    D --> F
    E --> F
図 2.1: if・elif・else による条件分岐。条件を上から順に調べ,いずれか一つの処理を実行する。

x の値を 3,0,-3 に変えて実行し,表示がどのように変わるかを確かめよう.

例 2.1 絶対値 |x| は,x \geq 0 のとき x となり,そうでないとき -x となる.if を使うと,次のように書ける.

x = -3

if x >= 0:
    print(x)
else:
    print(-x)  # 3
3

練習 2.1 変数 score に 75 を代入し,score が 60 以上なら 合格,そうでなければ 不合格 と表示せよ.

2.2 繰り返し

同じ処理を何度も行うには,for 文または while 文を使う.if 文と同じように,繰り返す処理はインデントして書く.

2.2.1 for

for 文は,リストなどから要素を一つずつ取り出して処理するときに使う.range(n) を使うと,0 以上 n 未満の整数を,小さい順に 1 ずつ取り出せる.ここで,n は整数とする.例えば,range(3) からは 0,1,2 が取り出され,3 は含まれない.

for i in range(3):
    print(i)
0
1
2

リストを使うと,その要素を先頭から順番に取り出すことができる.

fruits = ["apple", "banana", "cherry"]

for fruit in fruits:
    print(fruit)
apple
banana
cherry

range(a, b) を使うと,a 以上 b 未満の整数を,小さい順に 1 ずつ取り出せる.ただし,a と b は整数とする.a が b 以上の場合,取り出す整数はなく,for 文の中の処理は一度も実行されない.

次のコードは,1 から 5 までの整数の和を求める.変数 total に 0 を入れておき,繰り返しのたびに i を足していく.

total = 0

for i in range(1, 6):
    total = total + i

print(total)  # 15
15

練習 2.2 for を使って,1 から 10 までの整数の和を求めよ.

2.2.2 while

while 文は,条件が成り立つあいだ,同じ処理を繰り返す.回数を指定するのではなく,条件によって繰り返しを続けるかどうかを決めたいときに使う.

例 2.2 次のコードでは,x が 10 未満のあいだ,値を 2 倍にする.

x = 1

while x < 10:
    x = x * 2

print(x)  # 16
16

x の値は,1,2,4,8,16 と変化する.16 になると条件 x < 10 が成り立たなくなるため,繰り返しが終了する.

図 2.2 に示すように,x を更新するたびに条件の判定へ戻る.print(x) は繰り返しの外にあるため,終了後に一度だけ実行される.

%%{init: {"theme": "neutral"}}%%
flowchart TD
    A["x = 1"] --> B{"x < 10"}
    B -->|True| C["x = x * 2"]
    C --> B
    B -->|False| D["print(x)"]
図 2.2: while 文の処理の流れ。更新後は条件を再び調べ,False になったら繰り返しを終える。

条件は,処理を実行する前に毎回確認される.最初から条件が成り立たない場合,処理は一度も実行されない.

繰り返しの途中で条件が成り立たなくなっても,その回の残りの処理は実行され,次に条件を確認したときに繰り返しが終わる.条件が成り立ち続け,途中で抜け出す処理もなければ,繰り返しは終わらない.このような繰り返しを「無限ループ」という.

練習 2.3 1 枚の紙を半分に切ると 2 枚になり,そのすべてをさらに半分に切ると 4 枚になる.このように,すべての紙を半分に切る操作を繰り返す.紙の枚数が初めて 100 枚以上になるまでに,この操作を何回繰り返す必要があるか.while を使って求めよ.

2.3 関数の定義

これまでは,Python に用意されている関数を呼び出してきた.自分で関数を定義すると,一連の処理に名前を付け,引数を変えて繰り返し利用できる.Python では,def を使って関数を定義する.

例 2.3 f(x) = 2x + 1 を計算する関数 f を定義する.

def f(x):
    return 2 * x + 1

print(f(3))  # 7
print(f(5))  # 11
7
11

def の後ろに関数名を書き,丸括弧の中に引数を受け取る変数名を書く.行末には : を付け,関数の中で行う処理はインデントして書く.return は,値を呼び出し元に返し,関数の処理を終了する.

f(3) を呼び出すと,x に 3 が渡され,2 * 3 + 1 の計算結果である 7 が返される.その値を print() が画面に表示する.

関数は,定義しただけでは中の処理を実行しない.f(3) のように呼び出すと,処理が実行される.画面への表示と値を返すことは異なる.print() の戻り値は,値がないことを表す特別な値 None であり,表示した値ではない.

関数 f の戻り値は,表示するだけでなく,変数に代入して,その後の計算に使うこともできる.

result = f(3)
print(result + 10)  # 17
17

例 2.4 複数の引数を受け取る関数も定義できる.次の関数 sum_squares は,2 つの数を受け取り,それぞれを 2 乗して足した値 x^2 + y^2 を返す.

def sum_squares(x, y):
    return x**2 + y**2

print(sum_squares(3, 4))  # 25
25

引数はカンマで区切って書く.この呼び出しでは,x に 3,y に 4 が渡される.

練習 2.4 数値のリストを受け取り,要素の平均を返す関数 mean_value を定義せよ.sum() と len() を使うこと.ただし,リストには少なくとも 1 つの要素があるものとする.

また,リスト [2, 4, 6, 8, 10] を使って関数を呼び出し,戻り値を表示せよ.

2.4 モジュール

モジュールとは,関数などの機能をまとめたものである.モジュールを利用すると,必要な処理をすべて自分で書かなくても,既存の機能を使うことができる.

モジュールを利用するには,import 文を使う.例えば,数学関数を提供する math モジュールは,次のようにインポートする.math は Python の標準ライブラリに含まれており,追加のインストールは必要ない.

import math

モジュール内の関数は,モジュール名.関数名(引数) の形で呼び出す.次のコードでは,math モジュールの sqrt() 関数を使って,16 の正の平方根を求める.

result = math.sqrt(16)
print(result)  # 4.0
4.0

2.4.1 別名を付ける

import 文で as を使うと,モジュールに別名を付けられる.次のコードでは,math に m という別名を付け,m.sqrt() と書いて関数を呼び出している.

import math as m

print(m.sqrt(16))  # 4.0
4.0

ここでは書き方を示すために別名を付けたが,math は通常,そのままの名前で使う.次章で扱う NumPy は,import numpy as np と書き,np という短い別名で使うことが多い.

2.4.2 関数名を直接使う

from モジュール名 import 関数名 と書くと,モジュール名を付けずに,関数名だけで呼び出せる.

from math import sqrt

print(sqrt(16))  # 4.0
4.0

2.4.3 インポートを実行するタイミング

Google Colab では,モジュールを使うコードより先に,対応する import 文を実行しておく.同じランタイム(コードを実行する環境)であれば,セルが異なっていても,インポートしたモジュールを利用できる.ただし,ランタイムを再起動した場合は,変数や関数の定義も失われるため,import 文を含め,必要なコードをもう一度実行する.

練習 2.5 math モジュールをインポートし,sqrt() 関数を使って,81 の正の平方根を求め,結果を表示せよ.

2.5 総合練習

練習 2.6 数値のリストを引数として受け取り,0 より大きい要素の個数を返す関数 count_positive() を定義せよ.for と if を使うこと.また,リスト [-2, 0, 3, 5, -1] を使って関数を実行し,結果を表示せよ.

2.6 まとめ

  • インデントによって,処理のまとまりを表す.
  • if は条件によって処理を分け,for と while は処理を繰り返す.
  • 関数を定義すると処理を再利用でき,モジュールをインポートすると既存の機能を利用できる.

チャプター 3 では,import で NumPy を読み込み,配列を使って複数の値をまとめて計算する方法を学ぶ.