第5回 プログラムをきれいにする

6. リストを使って書き直す

このプログラムでも要件は満たしますが、少し工夫した書き方をしてみましょう。
今のコードでは、球種を増やしたり変えたりする際、最初のプロンプトメッセージと、次のif文の2箇所をずれないように直す必要があります。今回は影響も2箇所と少ないですし、球種もそんなには変動しないと思われますが、この変更が大変なプログラムではそうはいきません。この直しやすさのことを「保守性」といいます。具体的な修正例を見ながら学習してみましょう。

ソースコード

import sys
import time

species = ["ストレート", "カーブ", "シュート", "フォーク"]
print("何を投げますか?")
num = 0
for sp in species:
    num = num + 1
    print(str(num) + ". " + sp)
pitch = int(input(">> ")) - 1
print(species[pitch] + "を投げた!")
for i in range(10):
    time.sleep(0.2)
    sys.stdout.write('・')
何を投げますか?
1. ストレート
2. カーブ
3. シュート
4. フォーク
>> 2
カーブを投げた!
・・・・・・・・・・

■解説

0. このプログラムを理解するのに必要な知識
  1. リストを使うと複数の値を一括で扱える
  2. for文でリストの内容を1つずつ扱う
  3. +演算子で文字の結合
  4. 数値型と文字列型の違いと変換
  5. インデックスを指定してリストの値を参照する
1. リストを扱う

pythonにはリストという変数の型があります。
おみくじではfortuneという変数が登場し、中身は整数でした。同じように文字列を保持する変数もありますが、その他に複数の値を格納するリストという型があります。

変数 = [値1, 値2, ...]

リストを作成するには、「[ ]」(角カッコ、ブラケット)で囲み、複数の値を「,」(カンマ)で区切ります。値が固定の文字列の場合、「'」「"」で囲み、変数を使うこともできます。

2. for文でリストを扱う

for文は繰り返しの構文ですが、実は、リスト*1をひとつずつ取り出しながら繰り返し処理を実行します。

for 変数 in リスト:
    繰り返すコードブロック

リストの要素を変数に代入しながら続くコードブロックを繰り返し実行します。
f:id:inato_gen:20190219194549j:plain
つまり、

species = ["ストレート", "カーブ", "シュート"]
for sp in species:
    print(sp)

の動作はコードで表すと次のようなことになります。

sp = "ストレート" #speciesの1つ目
print(sp)
sp = "カーブ" #speciesの2つ目
print(sp)
sp = "シュート" #speciesの3つ目
print(sp)
#終わり
おみくじで登場した次のfor文
for i in range (10):
では、変数がi、リストがrange(10)となっています。range関数は、この書き方だと0から始まる10個の連続した数字を持つリストを返します*2。 つまり今回覚えた書き方で表すと
rng = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
for i in rng:
のようなイメージとなります。これで10回繰り返すことを実現していたんですね!
3. 文字列の結合

複数の文字列を結合(連結)するには+演算子を使います。

文字列 + 文字列 #連結した文字列を返す

+演算子は加算の演算子でもあります。どちらで動作するかは左右のデータ型によって決まります。
そのため、「数値 + 文字列」と記述するとエラーになります。

4. 文字列型と数値型の違い

その名の通りですが、

文字列型:文字としてのデータ(名前やメッセージなど)「'」や「"」で囲む。「数字」でも文字として扱われる
数値型:計算が可能な数値データ

具体的に見てみましょう。

text = "1"
num = 1
print(text)
print(num)
1
1

特に違いはありませんね。
では演算してみます。

print(text + text)
print(num + num)
11
2

違いが出ました。これは文字列は文字結合ができるのに対して、数値型は数学的な(算数?)扱いとして加算ができたということです。

文字列から整数に変換するにはint関数を使います。数値に変換できない文字の場合、エラーになります。

num = 1
text = "2"
print(num + int(text))
 3

逆に数値から文字列にするにはstr関数を使います。

print(str(num) + text)
12
5.リストの要素に対するアクセス

リストは複数の値をまとめて管理できるデータ型ですが、その1つの値を参照するには、どうすればよいでしょうか?
リストの何番目の値が欲しいかを指定して参照することができます。この「何番目」のことをインデックスまたは添字といい、次のように記述します。

print(species[0])
ストレート

リストの添字は0から始まります。図にすると次のような構造になります。
f:id:inato_gen:20190221202647j:plain
また、添字は数値型の値であればいいので変数が使えます。これによってユーザーが入力した番号に対応する球種を取得しています。

ただし、この場合はデータの型についで注意が必要です。input関数の戻り値は文字列、添字に必要なのは数値でした。なので変換が必要です。
pitch = int(input(">> "))
print(species[pitch])
動作を追いかけてみましょう。
#1が入力されたものとする
pitch = int("1") #文字列の1
pitch = 1 #数値の1に変換
pitch = 1
#代入演算子が処理されて変数pitchの値が1になる
print(species[1]) #変数pitchの値を展開
print("カーブ") #リストの要素を取得
print("カーブ")
#print関数が実行され、「カーブ」と表示される

*1:正確にはシーケンス型オブジェクト

*2:正確にはrange型のオブジェクトです