こんにちは、森山です。
前回のコラムでは、複数のデータをまとめて管理できる「リスト型」について学びました。 「リスト型」は、番号付きのポケットに順番にデータを入れておける便利な「箱」のような存在でしたね。
今回は、その復習として簡単なゲームを作りながら、さらにステップアップしてPythonらしいスマートな書き方である「リスト内包表記」について学んでいきましょう。
リストを使って「いつ・どこでゲーム」を作ろう
皆さんは、「いつ」「どこで」「誰が」「何をした」という言葉を紙に書いて、それぞれの箱に入れ、1枚ずつランダムに取り出して面白い文章を作る遊びをしたことはありませんか?
プログラミングの考え方もこれと同じで、それぞれの要素を「リスト」の中に入れ、中身を取り出して1つの文章を作ります。
このゲームをPythonで作るのに必要になるのが「繰り返し処理」と前回学んだ「リスト」です。リストにまとめたデータを、for文で1つずつ取り出して文章を組み立てます。
ランダムに取り出すために、今回も randomモジュール を使って作ってみましょう。
import random
# いつ
when_list = ["放課後に", "深夜2時に", "テスト5分前に", "授業中に", "日曜の朝に"]
# どこで
where_list = ["教室で", "屋上で", "トイレで", "満員電車で", "コンビニで"]
# 誰が
who_list = ["俺が", "友達が", "先生が", "隣の席の子が", "校長先生が"]
# 何をした
what_list = ["筋トレを始めた", "急に歌い出した", "スマホを3回落とした", "哲学を語り出した", "全力で走り出した"]
# 二次元リスト(リストの中にリストを入れる)にまとめる
data = [when_list, where_list, who_list, what_list]
# ランダムに1つずつ取り出して文を作る
sentence = []
for i in range(len(data)):
sentence.append(random.choice(data[i]))
sentence = " ".join(sentence)
# 出力
print(sentence)ここがポイント!
- data という変数の中に、4つのリストを入れています。この「二次元リスト」は大量のデータを整理するのにとても便利です。
- random.choice はリストの中からランダムに要素を1つ選んでくれる関数でしたね。
- len(data) はリストの要素数(今回は4)を返します。range(4) とすることで、0, 1, 2, 3 と順番に数字を取り出し、ループを回しています。
- sentence = “” では 空の文字列を用意しています。この変数に、for文の中で単語を1つずつ追加していき、最終的に1つの文章を作っています。
- 文を作る所で使っている .join() は、リストの中の文字をつなげて1つの文章にする処理です。これがないと、単語がバラバラのままリストとして表示されてしまうため、文章として見やすくするために使っています。
「添え字(インデックス)」とは?
プログラムの中で data[i] と書かれている [i] の部分を「添え字」(またはインデックス)と呼びます。
この添え字には、本来は 0 や 1 といった「数字」が入ります。
リストから特定のデータを取り出すときに、「左から何番目か」を指定する番号です。
ただし今回は、同じ処理をくり返すために i という変数を使っています。
この i の中には、ループのたびに 0, 1, 2… と順番に数字が入っています。
ここで重要なお作法を思い出しましょう。Pythonでは「数は 0 から数え始める」というルールがありましたね。
- data[0] → when_list(0番目)
- data[1] → where_list(1番目)
この「添え字」を使ってデータを扱う手法は、大量の情報を処理するデータ分析などのプログラムで非常によく使われます。
for文のルールと「リスト内包表記」
これまで何度も登場した for 文には、書き方の決まったルールがありました。
- 行末に :(コロン) を付ける
- 繰り返したい処理の行頭に 「インデント(半角スペース4つ)」 を入れる
実は、このルールとは全く違う、もっと短く書ける別の書き方が存在します。それが「リスト内包表記」です。
今回は、ハイスクールPythonの5.6でも解説されている、このテクニックを学んでいきましょう。
リスト内包表記って何?
リスト内包表記とは、for文の処理を1行で書く方法です。
処理する内容はこれまでの for 文と同じで、書き方が違うだけです。
どちらの書き方で書いても正解ですが、他の人が書いたコードを読むために「読めるようにしておくこと」はとても大切なので、書き方のルールは覚えておきましょう。
リスト内包表記の書き方のルール
リスト内包表記は、次の形で書きます。
[処理 for 変数 in リスト]
リストの中に、for文を書いているイメージです。
ゲームのプログラムをリスト内包表記で書いてみよう
先ほどのゲームで「各リストからランダムに選んで文章を作る処理」をリスト内包表記で書くと、以下のようになります。
import random
when_list = ["放課後に", "深夜2時に", "テスト5分前に", "授業中に", "日曜の朝に"]
where_list = ["教室で", "屋上で", "トイレで", "満員電車で", "コンビニで"]
who_list = ["俺が", "友達が", "先生が", "隣の席の子が", "校長先生が"]
what_list = ["筋トレを始めた", "急に歌い出した", "スマホを3回落とした", "哲学を語り出した", "全力で走り出した"]
data = [when_list, where_list, who_list, what_list]
# リスト内包表記でランダムに単語を取り出す
words = [random.choice(d) for d in data]
# 文を作る
sentence = " ".join(words)
print(sentence)何が変わったのか
繰り返し処理を作っているこの部分がポイントです。
words = [random.choice(d) for d in data]慣れるまでは、少し難しく見えるかもしれません。
でも、落ち着いて見ていくと、やっていることはそれほど難しくありません。
この1行は、もともとfor文で書いていた「各リストから1つずつランダムに選んで、新しいリストに入れる」という処理を、短くまとめて書いているだけです。
次のように1つずつ読むとわかりやすくなります。
- for d in data で data の中から1つずつ取り出す
- random.choice(d) の部分で取り出したリストの中からランダムに1つ選ぶ
- その結果を新しいリストとして words という変数に入れる
という流れです。
リスト内包表記で書くとコードがスッキリする
今回学んだ「リスト内包表記」は、数行に分けて書いていたコードをスマートに書くためのテクニックです。
for文を使ったプログラムを作るときは、ぜひリスト内包表記にも挑戦してみてください。
最後までお読みいただき、ありがとうございました。
それではまた次回お会いしましょう!
