見出し画像

ゆるいPython [2]

前回からの続きです。


状態

「なにを」の部分には数値モデルを,「どうする」の部分には計算モデルを使うのがプログラムの基本です。数値にできることならなんでも,プログラムにすることができます。計算にできることならなんでも,プログラムで答えを得るための手段にできます。
基本的なプログラムでは,変数をプログラムの入口として使います。変数を使って数に名前をつけることで,課題の定義をするのです。そして変数を使って計算をすることで,知りたい答えを得ることができます。
変数はプログラムの入口として使われるだけでなく,出口としても使われます。次のPythonのプログラムを見てみましょう。実行してみたい人は,こちらのリンクをクリックしてください。Googleのアカウントでログイン,左の三角ボタンを押して実行,警告表示で「そのまま実行」は覚えましたか?

最大血圧 = 150  # 単位はmmHg

厚生労働省の基準によると,最大血圧が140mmHg以上だと高血圧と診断されます。この状態では,健康体の維持に支障が出そうです。続けて,次のプログラムを見て下さい。

最大血圧 = 130  # 血圧が下がった

同じ変数名に130という新しい数が代入されました。Pythonで同名の変数に再代入を行うと,値の更新が行われます。変数に入っている数が変わるのです。
プログラムが2行あることは,時間の差を連想させます。そこから,高血圧の症状が改善された,というようなストーリーを思い浮かべることができます。変数に時間差で別の数を代入することで,プログラムで「状態」の変化を表現しているものと見なすことができます。
計算を使うと「変化」を表現することができます。計算を使って変数の数を変化させることでも,プログラムでストーリーを描くことができます。

毎月の小遣い = 1200
毎月の小遣い = 毎月の小遣い+300

2行目では,変数に500を追加した計算結果を,同じ名前の変数に代入しています。変数を使って計算した数を再代入することで,変数の中に入った数を更新しているのです。一ヶ月の小遣いが1200円から300円増えた,ということが読み取れます。
変数を追加することで,小遣いが増えた理由を表現できます。新しい状態を追加しましょう。

毎月の小遣い = 1500
テストの平均点 = 90

続けて,次のプログラムを読んでみましょう。

# 平均点が80点以上なら,小遣いが2倍になる
if テストの平均点 > 80:
    毎月の小遣い = 毎月の小遣い*2

このプログラムでは,「テストの平均点」が80以上だったときだけ,右に寄った部分のプログラムを実行する,という動きになります。変数には90という数が入っています。条件を満たすので,次の行が実行されて,毎月の小遣いが2倍になります。
一つ前のプログラムで,点数を70点にした場合はどうなるでしょうか。右に寄った部分のプログラムが実行されず,小遣いの値上げはなくなります。条件に従ってプログラムが枝分かれするため,このようなプログラムは「条件分岐」と呼ばれています。
Pythonでは,このようにして変数を使った条件を使った「ルール」をプログラムにすることができます。「if(もし)」という英語の後に,条件を書きます。条件が成り立った場合に実行したいプログラムは,右に寄せて書きます。これが簡単なルールです。
関数定義でも,右に寄ったプログラムが出てきました。このように左側にスペースを空け,右に寄せてプログラムを書くことを「インデント」と呼びます。プログラムの中で特別な扱いを受ける部分が,Pythonにとっても人間とっても分かりやすくなる書き方です。
変数の状態を調べ,状態に応じてプログラムを振り分けるという「ルール」を使ったプログラムは,単純な計算だけでは作ることができません。条件分岐を使うことで,プログラムで表現できることが広がります。

離散と連続

Pythonのプログラムでは,変数と数を組み合わせて「何を」の部分を記述します。変数をいくつも使うと,「何を」の部分をより詳しく表現することができるのです。変数と数を使って,ゲームの登場人物を表現してみます。

# 勇者
体力 = 50
魔法力 = 20
経験値 = 0

これまで,変数には「連続数」を代入してきました。連続数はたいてい単位を伴っていて,小数点以下に細かく区切ることができます。
「離散数」を使うと表現がさらに豊かになります。プログラムで使われる離散数は,複数の状態を数で表現するために使われることがあります。「毒のステータス異常」を表現するために,変数と離散数を使ってこのようなプログラムを作ることができます。0と1を使って,ある状態の「なし・あり」を表現する手法は,よく使われます。

毒 = 1

毒のステータス異常があるときだけ体力を2減らす,というプログラムです。変数がある数と同じかどうかを調べるには「==」という記号を使います。

if 毒 == 1:
    # 毒のステータス異常がある場合
    体力 = 体力-2

離散数を使って,職業を変数で表現します。

職業 = 1  # 1:勇者 2:魔法使い 3:修道士

1から3までの離散数をいろいろな職業に割り当てる「ルール」を決めることで,数と変数で職業を表現できるのです。この手法は強力で,プログラムの表現力をとても高めることができます。たとえば,職業の状態によってプログラムの流れを変えることで,魔法の効果を増やすことができます。職業に代入した数を2に変えて下のプログラムを動かすと,体力が10ではなく20回復します。

体力の回復量 = 10
if 職業 == 2:
    # 魔法使いは魔法が得意
    体力の回復量 = 体力の回復量*2
体力 = 体力+体力の回復量

変化する数

Pythonでは,「変化する数」を変数に入れることができます。「変化する数」とは,例えばテストの平均点などです。過去何回かの平均点を,順番に並べて変数に入れてみましょう。

テストの平均点 = [75, 82, 88, 85]  # 新しい順

テストの平均点を「新しい順に並べる」というルールを設けることによって,数を並べることができます。テストの平均点という同じ種類の数に「順番」という情報を付け加えることで,並べて表現できるようになるのです。
このように時間に沿って並べた数のことを「時系列データ」と呼びます。時系列データはプログラムでよく利用されます。ものごとが変化する様子を表現するための手法として便利だからです。
「3時間ごと」というルールを使って,降水確率を順番に並べてみましょう。テストの点数の例と同じく,これも同じ種類の数を並べてできるデータの仲間です。

降水確率 = [30, 10, 0, 0, 5, 0] # 3時間ごと

このように,角括弧で囲んでコンマで区切って数を並べたもののことを,Pythonでは「リスト」と呼んでいます。順番に並べた数は,順番を使って取り出すことができます。角括弧の中に,数を入れて順番を指定してリストの中にある数を取り出してみましょう。次のプログラムを実行すると,変数に代入したリストの一番最初の数「30」が取り出されます。

降水確率[0]  # 0番目の降水確率を取り出す

Pythonのリストでは,順番のことを「インデックス」と呼びます。インデックスは1からではなく0から始まり,1ずつ増えて行きます。これがインデックスのルールです。インデックスは離散数の一種です。
インデックスを使うと,リストの中から要素を取り出せることが分かりました。変数に入っているリストの要素はどちらも数なので,2つの要素を取り出して計算を実行できます。リストには新しい順で点数が入っていることを思い出して下さい。次のプログラムは「82-75」の計算をしたのと同じ結果を返します。

# 直近2回の平均点の差を計算する
テストの平均点[1]-テストの平均点[0]

順番に計算する

時系列データは,時間という「制約」を使って数を並べる一種のモデルと考えることができます。0から始まるインデックスというさらに強い「制約」を導入し,数を整然と並べてプログラムに書き入れるためにリストを使います。
なぜそうまでして制約を設けて数を並べるのかというと,利点があるからです。例えば,降水確率が入ったリストを使って,平均降水確率を計算したいと思います。3時間ごと6つなので,18時間の平均降水確率を計算することになります。

降水確率 = [10, 20, 90, 10, 5, 0] # 3時間ごと

平均は,「各要素を足す」と「要素数で割る」という二つの手順で計算できます。まず欲しいのは要素の合計数です。合計を足して行くためには変数を使いましょう。最初に0を代入しておきます。

合計 = 0  # この変数に合計を足して行く

この変数に,リストの要素を順番に足して行きましょう。最後に「135÷6」を計算するので,答えは「22.5」になります。

合計 = 合計+降水確率[0]  # 合計は10
合計 = 合計+降水確率[1]  # 合計は30
合計 = 合計+降水確率[2]  # 合計は120
合計 = 合計+降水確率[3]  # 合計は130
合計 = 合計+降水確率[4]  # 合計は135
合計 = 合計+降水確率[5]  # 合計は135
合計/6   # 平均を計算

上の6行を見ると,リストに続く角括弧の中に書かれた0から5までのインデックス以外の部分は,プログラムとしてはまったく同じであることが分かります。角括弧の中には,数に相当するものであればなんでも置くことができるので,離散数を代入した変数を添えることができます。インデックスを変数で表現すると,共通部分がさらに増えます。合計を足したあと,インデックスを1ずつ増やして行けば,前のプログラムと同じ手順が実行できるからです。

合計 = 0
インデックス = 0
合計 = 合計+降水確率[インデックス]
インデックス = インデックス+1
合計 = 合計+降水確率[インデックス]
インデックス = インデックス+1
# 上の2行をあと4回,合計6回繰り返す

足し算を使って変数の数を更新するときには,「+=」という記号を使うと便利です。変数を元にした計算と,変数への代入を同時に実行できます。「インデックス = インデックス+1」と同じ事をするプログラムを,「インデックス += 1」というように短く書くことができます。後で使って見ましょう。
2つのプログラムを比較すると,下の方では計算の手順が共通になることでモデル化されているのが分かります。リストを使うことで時系列データを扱うための計算手順が単純になり,共通化されます。手順を共通化することはとても重要な意味を持っています。共通部分が見いだされると手順が「モデル化」され,プログラムで扱いやすくなるからです。
Pythonには,リストの各要素について同じプログラムを動かしたいときに使う特別な記法があります。平均を計算するプログラムを,「ループ」を使って書き換えてみましょう。合計を足す部分は「+=」をうまく使って簡潔に書いてみます。

合計 = 0
for 要素 in 降水確率:
    合計 += 要素

まず,変数名に注目しながら,Pythonでループを作るときのルールを簡単に解説します。「for」から始まる行でループを始めるのが記法のルールです。一番右側,inの後にはリストの入った変数が見えます。forとinの間に見えるのは「繰り返し変数」と呼ばれる変数の一種です。繰り返し変数は,インデントされた部分に再度現れています。
変数についておさえたら,ループで何が起こるのかを確認しましょう。ループでは,降水確率のリストから数を一つずつ取り出し,「要素」という変数に代入します。その状態でインデントされたプログラムが実行されます。これを,inの右にあるリストの先頭から最後まで繰り返し実行します。このようにして,リストの要素すべてについて「合計」という変数に足してゆく,という手順を,この2行で実行できるのです。
合計という変数に入った数を,リストに入った数の要素数で割れば,平均が計算できます。

合計/6

次のプログラムを見て下さい。先ほどのプログラムの違いは,ループのインデントの中にifのインデントがあることです。

最大値 = 0
for 要素 in 降水確率:
    if 要素 > 最大値:
        最大値 = 要素

Pythonのループを理解するための秘訣は,頭の中でプログラムの動きを追ってみることです。inの右に添えたリストは,先ほどと同じです。リストの要素をひとずつ繰り返し変数に代入しながら,インデントの中に書いてあるプログラムを,頭の中で実行してみましょう。
初回のループでは,繰り返し変数に10が代入されます。0で初期化された「最大値」という変数より大きいので,繰り返し変数が代入されて10になります。リストの数すべてについて同じ要領でループが実行され,結果としてリストの中の一番大きな数が「最大値」という変数に入った状態でループが終了します。

次の記事へ


拡散,応援,励みになっています!


この記事が気に入ったらサポートをしてみませんか?