タートルグラフィックスで学ぶ Python のキホン 第 16 章
教材コード
第 16 章

リスト

同じ種類のデータは,1 つの箱にまとめて入れる.繰り返しと組み合わせると,一気に力が出ます.

変数は「数を 1 つ覚えておく箱」でした.では,覚えておきたい数が 5 つあったら? 100 個あったら? 変数を 100 個作って,100 行の命令を書くのでしょうか.

今回覚えるリストは,同じ種類のデータをまとめて入れる箱です. リストと,すでに習った繰り返しを組み合わせると, データが 5 個だろうと 100 個だろうと,プログラムの長さは変わりません. ここがプログラミングの大きな山のひとつです.

この章でできるようになること
  • [ ] でリストを作り,添字で 1 つずつ取り出せる
  • len() で個数を調べ,中身を書き換えられる
  • append()pop()remove() でリストを伸ばしたり縮めたりできる
  • for x in リストfor i in range(len(リスト)) を使い分けられる
  • 色・長さ・座標をリストに入れて,繰り返しで図を描ける
  • リストにかめを入れて,何匹でも一斉に動かせる
  • summaxmin を使い,条件に合うものを自分で数えられる
  • スライス・リストのリストを知っている

16.1 変数が増えてくると,こうなる

第 8 章で,5 匹のかめを動かしました.そのときのプログラムを思い出してください. かめ 1 匹につき変数を 1 つ作り,動かす命令も 1 匹ぶんずつ書きました.

5 匹のかめを動かす(第 8 章のやり方)
from turtle import *

t0 = Turtle()
t1 = Turtle()
t2 = Turtle()
t3 = Turtle()
t4 = Turtle()

t0.goto(-200, 0)
t1.goto(-100, 0)
t2.goto(0, 0)
t3.goto(100, 0)
t4.goto(200, 0)

t0.fd(80)
t1.fd(80)
t2.fd(80)
t3.fd(80)
t4.fd(80)

動きはします.けれども,このプログラムには 3 つの困りごとがあります.

  1. 増やすのが大変.かめを 20 匹にしたければ,変数を 15 個足し,命令も 15 行 × 2 か所ぶん書き足さなければなりません.
  2. 直すのが大変.fd(80)fd(120) に変えたければ,5 か所すべてを直します.1 か所忘れたら,そのかめだけ違う動きをします.
  3. 「全部に」ができない.「いちばん進んだかめは?」「全部のかめの合計は?」といったことを調べるのに,毎回 5 つの変数を並べて書く必要があります.
繰り返し書きたくなったら,道具が足りていない 同じような命令が縦にずらずら並んだら,それは 「コンピュータにやらせるべきことを,人間が手で書いている」合図です. 第 6 章では「同じ命令の繰り返し」を for に任せました. 今回は「同じ種類のデータの並び」をコンピュータに任せます. そのための道具がリストです.

16.2 リストに入れる

16.2.1 リストを作る — [ ]

リストは,角かっこ [ ] の中に,コンマで区切って並べて作ります. 数でも文字でも,何を入れてもかまいません.

リストの作り方
scores = [80, 95, 72, 100, 64]
colors = ["red", "green", "blue"]
empty  = []                        # 空っぽのリストも作れる
名前は複数形にする リストの変数名は,中身の名前の複数形にするのが習慣です. 点数なら score ではなく scores, かめなら turtle ではなく turtles. こうしておくと,for score in scores: のように プログラムが英語の文のように読めます.

16.2.2 取り出す — 添字は 0 から始まる

リストの中の 1 つを取り出すには,何番目かを角かっこで指定します. この番号を添字(そえじ,index)といいます. ここで最初に必ずつまずくのですが, 添字は 1 ではなく 0 から始まります

1 つめ2 つめ3 つめ4 つめ5 つめ
中身80957210064
添字01234
index.py
scores = [80, 95, 72, 100, 64]

print(scores[0])      # 1 つめ → 80
print(scores[1])      # 2 つめ → 95
print(scores[4])      # 5 つめ → 64

print(scores[-1])     # 最後 → 64
print(scores[-2])     # 後ろから 2 つめ → 100
コラム:なぜ 0 番から数えるのか なぜ 0 から始まるのでしょうか. コンピュータの中では,リストは「メモリのこの場所から並んでいる」という形で覚えられています. 先頭の要素は「先頭から 0 個ぶんずれた場所」にあるので,添字は 0 になります. この考え方が広まり,Python も 0 から始まる決まりになっています. 一方で「人間には 1 から始まるほうが自然だ」という立場もあり, 1 から始まる言語もあります.
よくあるエラー 5 個しかないリストで scores[5] と書くと, IndexError: list index out of range(範囲外)というエラーになります. 最後の添字は「個数 − 1」です.

角かっこの中には,数をそのまま書くだけでなく, 変数でも計算式でも書けます. ここが「変数を 5 個作る」やり方との大きな違いです. score3 という変数名は計算で作れませんが, scores[i]i なら計算で決められます.

kuji.py
import random

prize = ["特賞", "1 等", "2 等", "3 等", "はずれ"]

i = random.randint(0, len(prize) - 1)   # 0 から「個数 − 1」までのでたらめな数
print(i, "番目 →", prize[i])

# 同じことを 1 行で書く道具もある
print(random.choice(prize))

# 何度も引いてみる
for kai in range(5):
    print(kai + 1, "回目:", random.choice(prize))
範囲の指定を数字で書かない random.randint(0, 5) と書くと 0 から 5 まで, つまり 6 通りの数が出ます.5 個のリストには 5 番目がないので, ときどき IndexError になります. こういうときこそ len(prize) - 1 と書いてください. 個数を数字で書いてしまうと,リストを増やしたときに必ず忘れます

16.2.3 個数を数える — len()

len(リスト) で,入っている個数がわかります. プログラムの中に個数を直接書かないために,とても大事な命令です.

len.py
scores = [80, 95, 72, 100, 64]

print(len(scores))            # 5
print(scores[len(scores) - 1])  # 最後の要素 → 64

colors = ["red", "green", "blue"]
print(len(colors))            # 3
print(len([]))                # 0
ヒント len は length(長さ)の略です. 文字列にも使えて,len("こんにちは") は 5 になります.

16.2.4 書き換える

添字で場所を指定して,= で新しい値を入れれば書き換えられます. 変数への代入とまったく同じ書き方です.

assign.py
scores = [80, 95, 72, 100, 64]
print(scores)

scores[2] = 88        # 3 つめを 88 に
print(scores)

scores[0] = scores[0] + 10   # 1 つめに 10 点おまけ
print(scores)
虫食い虫食い 16-A 3 つの点を打つ

座標のリストから 1 つずつ取り出して,3 か所に点を打ちます. ____ を埋めてください. 添字は 0 からでしたね.

fill15_dots.py
from turtle import *

ht()
pu()

xs = [-180, 0, 180]
colors = ["crimson", "gold", "royalblue"]

goto(xs[0], 0)
dot(60, colors[____])

goto(xs[____], 0)
dot(60, colors[1])

goto(xs[2], 0)
dot(60, colors[____])

# 個数を表示する
goto(0, -120)
pencolor("dimgray")
write(f"点は {____(xs)} 個", align="center", font=("Arial", 22, "normal"))

done()

16.3 リストを伸ばす・縮める

リストは,あとから中身を増やしたり減らしたりできます. ここが「変数を 5 個作る」やり方との決定的な違いです. プログラムが動いている最中に,入れ物の大きさを変えられるのです.

命令意味
リスト.append(値)最後に 1 つ付け足す
リスト.insert(添字, 値)指定した場所に割り込ませる
リスト.insert(0, 値)先頭に 1 つ割り込ませる
a += ba.extend(b)リスト b の中身をまとめて a の最後に付け足す
b.extend(a) のあと a.clear()a の中身を全部 b へ移す(移したほうは空になる)
リスト.pop()最後の 1 つを取り出して,リストから消す
リスト.pop(添字)指定した場所の 1 つを取り出して,リストから消す
リスト.pop(0)先頭の 1 つを取り出して,リストから消す
リスト.remove(値)そのを探して,最初に見つかった 1 つを消す
リスト.clear()全部消して空にする
先頭の出し入れは少し高くつく insert(0, 値)(先頭に入れる)と pop(0)(先頭から取る)は, append()pop() に比べて少し手間がかかります. 先頭に場所を空けたり,空いた場所を詰めたりするために, 後ろの要素を全部ひとつずつずらす必要があるからです. 要素が 10 個くらいなら気になりませんが,何万個もあるときは差が出ます. とくに理由がなければ,後ろ(appendpop)を使ってください
append.py
scores = []
print(scores)

scores.append(80)
scores.append(95)
scores.append(72)
print(scores)            # [80, 95, 72]
print(len(scores))       # 3

last = scores.pop()      # 最後の 72 を取り出す
print(last)              # 72
print(scores)            # [80, 95]

scores.append(100)
scores.append(64)
print(scores)            # [80, 95, 100, 64]

scores.remove(95)        # 値 95 を消す(添字ではない)
print(scores)            # [80, 100, 64]
pop と remove を取り違えない pop添字で,removeで消します. scores.remove(2) は「3 つめを消す」ではなく 「2 という値を探して消す」です. 見つからなければ ValueError になります.
ドットの意味 scores.append(80) の書き方は,これまでの fd(100) とは 少し形が違います.「誰に」対する命令か.(ドット)の前に書くのです. 第 8 章で t1.fd(100) と書いたのと同じ形です. 「scores さん,80 を付け足してください」と読んでください.
虫食い虫食い 16-B 買い物かご

買い物かごに品物を入れたり出したりします. ____ を埋めてください. 付け足すのと,値を指定して消すのと, 個数を数えるのは,それぞれ何という命令でしたか.

fill15_kago.py
kago = ["りんご", "たまご"]

kago.____("ぎゅうにゅう")     # 付け足す
kago.append("パン")
print(kago)

kago.____("たまご")           # 「たまご」をやめる
print(kago)

print(f"かごの中は {____(kago)} 個です")
print(f"最後に入れたのは {kago[____]} です")

16.4 for でリストを回す

ここからが本番です.リストの力は,繰り返しと組み合わせたときに出ます. 書き方は 2 つあります.

16.4.1 for x in リスト — 中身を順に取り出す

for 変数 in リスト: と書くと, リストの中身が先頭から順に 1 つずつ変数に入り, そのたびに中の命令が実行されます.

for x in リスト の形
scores = [80, 95, 72]

for s in scores:
    print(s)

1 回目は s に 80 が,2 回目は 95 が,3 回目は 72 が入ります. リストが何個でも,プログラムの長さは変わりません. これが「コンピュータに繰り返させる」ということです.

forin.py
scores = [80, 95, 72, 100, 64]

for s in scores:
    print(f"点数は {s} 点")

print("---")

colors = ["red", "green", "blue"]
for c in colors:
    print(f"色は {c}")
range も「並び」だった 第 6 章で習った for i in range(5): も,じつは同じ形です. range(5)0, 1, 2, 3, 4 という並びを作り, それを 1 つずつ i に入れていたのです. for は「並んでいるものを順に取り出す」命令だと 覚えておいてください.

16.4.2 for i in range(len(リスト)) — 添字で回す

もうひとつの書き方は,添字のほうを回すやり方です. range(len(リスト))0 から 個数 − 1 までを順に作るので, それを添字として使えば,やはり全部をなめられます.

for i in range(len(リスト)) の形
scores = [80, 95, 72]

for i in range(len(scores)):
    print(f"{i} 番目は {scores[i]} 点")
forindex.py
scores = [80, 95, 72, 100, 64]

for i in range(len(scores)):
    print(f"{i + 1} 人目は {scores[i]} 点")

print("---")

# 添字が使えると「書き換え」ができる
for i in range(len(scores)):
    scores[i] = scores[i] + 5      # 全員に 5 点おまけ

print(scores)

16.4.3 どちらを使うか

for x in リストfor i in range(len(リスト))
読みやすさとても読みやすいやや読みにくい
中身を使うそのまま使えるリスト[i] と書く
何番目かを知るわからないi でわかる
中身を書き換えるできないできる
2 つのリストを同時に使うできないできる

つまりまずは for x in リスト を使い, 「何番目か」が要るときや「書き換えたい」ときだけ添字で回す, と決めておけば迷いません.

よくある間違い for s in scores: の中で s = s + 5 と書いても, リストの中身は変わりませんs は中身を写しとった別の変数だからです. リストを書き換えたいときは,scores[i] = …添字を使って書いてください.
虫食い虫食い 16-C 合計と平均

点数のリストから,合計・人数・平均を求めます. ____ を埋めてください. 合計を入れておく変数は,0 から始めるのを忘れずに.

fill15_total.py
scores = [80, 95, 72, 100, 64]

total = ____

for s in ____:
    total = total + ____

print(f"合計は {total} 点")
print(f"人数は {____(scores)} 人")
print(f"平均は {total / len(scores)} 点")

16.5 リストの中身を使って図を描く

16.5.1 色のリスト

第 2 章では,辺ごとに色を変えるのに pencolor を何行も書きました. 色をリストに入れれば,3 行で済みます.

colors.py
from turtle import *

ht()
pu()

colors = ["#e74c3c", "#e67e22", "#f1c40f",
          "#2ecc71", "#3498db", "#9b59b6", "#34495e"]

x = -270
for c in colors:
    goto(x, 0)
    dot(70, c)
    x = x + 90

done()
図 16.1 色のリストを for で回した.色を足したいときはリストに 1 つ書き足すだけ.
長いリストは折り返す リストは 改行して書いてもかまいません[ ] が閉じるまでが 1 つの命令として扱われるので, 長いリストは上の例のように途中で折り返すと読みやすくなります.

16.5.2 長さのリスト — 棒グラフ

数のリストがあれば,そのまま棒グラフになります. 添字で回せば,何本目かもわかるので,横の位置を決められます.

bar.py
from turtle import *

ht()
scores = [80, 95, 72, 100, 64]
names = ["A", "B", "C", "D", "E"]

pensize(28)
pencolor("#3498db")

for i in range(len(scores)):
    x = -220 + i * 110         # i 本目の横位置
    pu()
    goto(x, -120)
    pd()
    goto(x, -120 + scores[i])  # 点数ぶん上へ

    # 名前と点数を書く
    pu()
    goto(x, -155)
    pencolor("dimgray")
    write(names[i], align="center", font=("Arial", 22, "bold"))
    goto(x, -110 + scores[i])
    write(scores[i], align="center", font=("Arial", 18, "normal"))
    pencolor("#3498db")

done()
A80B95C72D100E64
図 16.2 2 つのリスト(点数と名前)を同じ添字で使うと,棒と見出しを対応させられる.

ここでは scoresnames という 2 つのリストを同じ添字で使っています. scores[2]names[2] は同じ人のもの,という約束です. こういうときは for x in リスト では書けないので, 添字で回す書き方の出番になります.

16.5.3 座標のリスト

座標も数の並びですから,リストに入れられます. x のリストと y のリストを作って,同じ添字で取り出せば, 好きな形の折れ線が描けます.

poly.py
from turtle import *

ht()
pensize(4)
pencolor("#e74c3c")

xs = [-240, -150, -60, 30, 120, 210]
ys = [-80, 60, -30, 110, 10, 90]

pu()
goto(xs[0], ys[0])
pd()

for i in range(len(xs)):
    goto(xs[i], ys[i])
    dot(16, "#c0392b")

done()
図 16.3 座標のリストをたどって折れ線を描いた.データを差し替えれば,まったく違う形になる.
虫食い虫食い 16-D 辺ごとに色が変わる図形

色のリストを使って,辺ごとに色の変わる正六角形を描きます. ____ を埋めてください. 正六角形の曲がる角度は 360 ÷ 6, 繰り返す回数は色の個数と同じにします.

fill15_hexcolor.py
from turtle import *

pensize(10)
pu()
goto(-70, -100)
pd()

colors = ["crimson", "darkorange", "gold",
          "seagreen", "royalblue", "purple"]

for c in ____:
    pencolor(____)
    fd(120)
    rt(____)

ht()
done()

16.6 リストにかめを入れる

リストには数や文字だけでなく,かめそのものも入れられます. ここが今回いちばん強力なところです. 16.1 節の「変数を 5 個作る」問題が,これで解決します.

16.6.1 かめをまとめて作る

空のリストを用意し,for の中で Turtle() を作っては append していきます. 5 を 20 に変えるだけで 20 匹になるところを味わってください.

turtlelist.py
from turtle import *

ht()

turtles = []              # 空のリストを用意

for i in range(5):
    t = Turtle()          # かめを 1 匹作って
    t.shape("turtle")
    t.shapesize(1.6)
    t.pu()
    t.goto(-220, -80 + i * 45)   # i 番目の場所へ
    t.color("#3498db")
    turtles.append(t)     # リストに入れる

# 全員まとめて動かす
for t in turtles:
    t.pd()
    t.pensize(3)
    t.fd(150)

done()
図 16.4 5 匹をリストに入れ,for で一斉に進ませた.range(5)range(20) にすれば 20 匹になる.

かめごとに違う色にしたいときは,色のリストを添字で合わせます.

turtlelist2.py
from turtle import *

ht()

colors = ["#e74c3c", "#e67e22", "#f1c40f", "#2ecc71", "#3498db", "#9b59b6"]
lengths = [60, 110, 160, 210, 260, 310]

turtles = []
for i in range(len(colors)):
    t = Turtle()
    t.shape("turtle")
    t.shapesize(1.4)
    t.pu()
    t.goto(-260, -120 + i * 48)
    t.color(colors[i])
    t.pensize(5)
    turtles.append(t)

# i 番目のかめは lengths[i] だけ進む
for i in range(len(turtles)):
    turtles[i].pd()
    turtles[i].fd(lengths[i])

done()
図 16.5 色のリスト・長さのリスト・かめのリストを同じ添字でそろえて使った.

16.6.2 一斉に動かす

第 10 章の ontimer と組み合わせます. 1 コマの処理の中で for を回せば, 何匹いても 3 行で全員を動かせます.

race.py
from turtle import *
import random

ht()
bgcolor("#f6f7fb")

colors = ["#e74c3c", "#e67e22", "#f1c40f",
          "#2ecc71", "#3498db", "#9b59b6"]

turtles = []
for i in range(len(colors)):
    t = Turtle()
    t.shape("turtle")
    t.shapesize(1.4)
    t.pu()
    t.goto(-260, -130 + i * 52)
    t.color(colors[i])
    t.pensize(4)
    t.pd()
    turtles.append(t)

def step():
    for t in turtles:              # 全員に同じ命令
        t.fd(random.randint(2, 12))
        if t.xcor() > 260:
            t.pu()
            t.goto(-260, t.ycor())
            t.pd()
    ontimer(step, 80)

step()
done()

random.randint(2, 12) は 2 から 12 までのでたらめな整数を返します (使うには import random が要ります). 進む距離が毎回違うので,かめレースになります. かめの数を増やしたいときは colors に色を足すだけです. step の中は 1 文字も変えなくてよいことを確かめてください.

虫食い虫食い 16-E かめの隊列

4 匹のかめをリストに入れ,縦に並べて,一斉に同じ距離だけ進ませます. ____ を埋めてください.

fill15_squad.py
from turtle import *

ht()

turtles = ____              # 空のリスト

for i in range(4):
    t = Turtle()
    t.shape("turtle")
    t.shapesize(1.8)
    t.pu()
    t.goto(-200, -90 + i * 60)
    t.color("seagreen")
    turtles.____(t)         # リストに入れる

for t in ____:              # 全員に命令する
    t.pd()
    t.pensize(4)
    t.fd(____)

done()

16.7 リスト全体を調べる

合計や最大値は for で書いてもよいのですが, Python には最初から用意されています.

命令意味
len(リスト)個数
sum(リスト)合計(中身が数のときだけ)
max(リスト)いちばん大きい値
min(リスト)いちばん小さい値
値 in リストその値が入っていれば True
リスト.index(値)その値が何番目にあるか
リスト.count(値)その値がいくつ入っているか
sorted(リスト)小さい順に並べ替えた新しいリスト
stats.py
scores = [80, 95, 72, 100, 64]

print(f"個数  : {len(scores)}")
print(f"合計  : {sum(scores)}")
print(f"平均  : {sum(scores) / len(scores)}")
print(f"最高点 : {max(scores)}")
print(f"最低点 : {min(scores)}")

print(f"100 点はいる? : {100 in scores}")
print(f"100 点は何番目? : {scores.index(100)}")
print(f"並べ替え : {sorted(scores)}")
print(f"もとのまま : {scores}")
sorted と sort の違い sorted(scores)新しいリストを作って返すだけで, scores 自身は並び替わりません. scores そのものを並べ替えたいときは scores.sort() です. 並べ替えのしくみは,第 17 章で自分の手で組み立てます.

調べた結果は,第 11 章で覚えた write で画面に出せます. 棒グラフの上に平均線を引く,といったことも簡単です.

stats2.py
from turtle import *

ht()
scores = [80, 95, 72, 100, 64]
best = max(scores)

pensize(26)

for i in range(len(scores)):
    x = -220 + i * 110
    if scores[i] == best:
        pencolor("#e74c3c")      # 最高点だけ赤
    else:
        pencolor("#bdc3c7")
    pu()
    goto(x, -120)
    pd()
    goto(x, -120 + scores[i])

pu()
goto(0, 120)
pencolor("#2c3e50")
write(f"最高 {best} 点 / 平均 {sum(scores) / len(scores)} 点",
      align="center", font=("Arial", 24, "bold"))

done()
最高 100 点 / 平均 82.2 点
図 16.6 max で求めた最高点の棒だけ色を変えた.

ただし,できあいの道具でできるのは「全部の合計」「全部の最大」までです. 「60 点以上は何人か」のように 条件に合うものだけを集計したいときは,自分で書きます. 形は虫食い 16-C の合計とまったく同じで, 数える箱を 0 から始めて,for の中で 1 ずつ増やすだけです.

count.py
scores = [80, 95, 72, 100, 64, 55, 88, 43]

kazu = 0        # 数える箱.0 から始める
wa = 0          # 合計の箱.これも 0 から始める

for s in scores:
    if s >= 60:
        kazu = kazu + 1
        wa = wa + s

print("全部で", len(scores), "人")
print("60 点以上は", kazu, "人")
print("60 点未満は", len(scores) - kazu, "人")
print("60 点以上の人の平均は", wa / kazu, "点")

# 「ぴったりこの値」を数えるだけなら count() がある
print("100 点は", scores.count(100), "人")
リストと繰り返しの 4 つの型 合計する・数える・探す・いちばんを見つける. リストを for で回してやることは,たいていこの 4 つのどれかです. どれも「覚えておく箱を先に用意して,繰り返しの中で更新する」という 同じ形をしています. この形が手になじめば,リストを使ったプログラムはほとんど書けます. 探すことと,いちばんを見つけることは,次の第 17 章でくわしくやります.
箱を 0 にし忘れない 数える箱を 0 にし忘れると, NameError: name 'kazu' is not defined というエラーになります. また,条件に合うものが 1 つも無いときに wa / kazu を計算すると, ZeroDivisionError(0 で割った)で止まります. 平均を出す前に if kazu > 0: と確かめておくと安全です.

16.8 一部だけ取り出す — スライス

リスト[start:stop] と書くと, start 番から stop 番の手前までを切り出した新しいリストができます. これをスライスといいます. 「stop は含まない」のがポイントです.

slice.py
scores = [80, 95, 72, 100, 64, 88, 91]

print(scores[0:3])    # 0,1,2 番 → [80, 95, 72]
print(scores[2:5])    # 2,3,4 番 → [72, 100, 64]

print(scores[:3])     # 先頭から 3 つ
print(scores[4:])     # 4 番から最後まで
print(scores[-2:])    # 後ろから 2 つ
print(scores[:])      # まるごと写し

print(len(scores[1:4]))   # 4 - 1 = 3 個
なぜ stop を含まないのか 「stop を含まない」のは range(0, 3)0, 1, 2 になるのと同じ決まりです. おかげで [0:3] の個数はいつも 3 − 0 = 3 個と, 引き算だけで求められます.

16.9 リストの中にリストを入れる

リストには何を入れてもよいので,リストを入れることもできます. これを二次元のリスト(リストのリスト)といい, 表やマス目を表すのに使います.

二次元のリスト
board = [[1, 2, 3],
         [4, 5, 6],
         [7, 8, 9]]

print(board[0])       # [1, 2, 3]   ← 1 行目まるごと
print(board[0][2])    # 3           ← 1 行目の 3 つめ
print(board[2][0])    # 7           ← 3 行目の 1 つめ

board[行][列] の順で指定します. 取り出すときは,まず board[0] で「1 行ぶんのリスト」を取り出し, さらにその [2] 番目を取り出している,と読んでください.

grid.py
from turtle import *

ht()
pu()

board = [[1, 0, 1, 0, 1],
         [0, 1, 0, 1, 0],
         [1, 0, 1, 0, 1],
         [0, 1, 0, 1, 0]]

for row in range(len(board)):
    for col in range(len(board[row])):
        x = -200 + col * 100
        y = 130 - row * 100
        goto(x, y)
        if board[row][col] == 1:
            dot(80, "#2c3e50")
        else:
            dot(80, "#ecf0f1")

done()
図 16.7 01 を並べた表から模様を作った.表の数字を書き換えれば模様が変わる.
for を 2 段に重ねる 二次元リストを回すときは,for を 2 段に重ねます (第 7 章の「繰り返しの入れ子」です). 外側が,内側がと決めておくと混乱しません.

この形は,第 12 章でゲームの地図(どこに壁があるか)を表すのに使います. 今は「こういう書き方がある」と知っておけば十分です.

16.10 この章で出てきた命令

書き方意味
xs = [10, 20, 30]リストを作る
xs = []空のリストを作る
xs[0]1 つめを取り出す(添字は 0 から)
xs[-1]いちばん後ろを取り出す
xs[1] = 992 つめを書き換える
len(xs)個数
xs.append(値)最後に付け足す
xs.insert(添字, 値)途中に割り込ませる
xs.pop()最後を取り出して消す
xs.pop(添字)その場所のものを取り出して消す
xs.remove(値)その値を探して消す
for x in xs:中身を順に取り出して繰り返す
for i in range(len(xs)):添字を順に作って繰り返す
sum(xs) max(xs) min(xs)合計・最大・最小
値 in xs入っているかどうか(TrueFalse
xs.index(値)その値が何番目か
xs.count(値)その値がいくつ入っているか
random.choice(xs)でたらめに 1 つ選ぶ(import random が要る)
sorted(xs)小さい順に並べた新しいリスト
xs[1:4]スライス.1 番から 4 番の手前まで
board[行][列]二次元リストの 1 マス

演習

「▶ この演習を開く」で右側に読み込み,発展させてください. できあがったら「⤓ 保存」でファイルに保存して,手元に残しておきましょう.

演習演習 16-1 自分のデータで棒グラフ

棒グラフを描くプログラムを与えます. リストの中身を自分のデータに差し替えて, 意味のあるグラフにしてください. 1 週間の勉強時間,好きな食べ物の点数,科目ごとの得点 — 何でもかまいません.

  • データは 5 個以上にすること
  • max を使って,いちばん大きい棒だけ色を変えること
  • sumlen で平均を計算し,write で表示すること
ヒント データの個数を変えたら,横幅や棒の間隔も調整が要ります. x = -220 + i * 110110 が間隔です.
演習演習 16-2 色のリストで模様

色のリストを使って模様を描くプログラムを与えます. 色を足したり減らしたり,角度や長さを変えたりして, 自分の模様に発展させてください.

出発点の模様
演習演習 16-3 リストを育てる

appendpop を使って, 点を打った場所を覚えておくプログラムを作ります. 出発点では 3 か所に打つだけです.次のように発展させてください.

  • for を使って 10 か所以上に打つこと
  • 打った座標をリストに append していくこと
  • 最後に,打った場所を線でつなぐこと(リストを for で回して goto
  • len で個数を write すること
演習演習 16-4 かめの大群

リストにかめを入れて一斉に動かすプログラムを与えます. 次のように発展させてください.

  • かめの数を 10 匹以上にすること
  • 色をリストにして,1 匹ずつ違う色にすること
  • 進む距離か曲がる角度もリストにして,1 匹ずつ変えること
ヒント 色を 10 個書くのが面倒なら, "#%02x60c0" % (20 + i * 22) のように 計算で色を作る手もあります (%02x は数を 2 桁の 16 進数にする書き方です).
演習演習 16-5 かめレース

リストのかめを ontimer で一斉に動かす「かめレース」です. 出発点は 4 匹がでたらめに進むだけです.次のように発展させてください.

  • かめの数を増やすこと(リストに色を足すだけで増えるはずです)
  • ゴールの線を引くこと
  • 誰かがゴールに着いたら,write勝者を発表して止めること
ヒント 止めるには,ontimer呼ばずに関数を終えるだけです. 「誰がゴールしたか」を知るには, for i in range(len(turtles)): で添字も一緒に回し, colors[i] や名前のリストを使います.
演習演習 16-6 二次元リストでドット絵

01 を並べた表から模様を作るプログラムを与えます. 表を書き換えて,自分のドット絵を作ってください. ハート,顔,文字,キャラクター — 方眼紙に下書きしてから写すと楽です.

  • 表は 縦 6 行 × 横 6 列以上にすること
  • 0 1 だけでなく 2 も使い,3 色にすること(elif を足します)
ヒント マスの大きさは dot(80, …)80 と, col * 100 row * 100100 で決まります. 行や列を増やしたら,この数を小さくしてください.
自由演習 16-7 自由制作:データで絵を描く

リストを使った作品を自由に作ってください. 「データを差し替えると絵が変わる」ことが伝わる作品にしてください.

  • リストを 2 つ以上使うこと
  • for でリストを回して描くこと
  • len を使い,個数を直接書かないこと(リストの中身を増やしても,そのまま動くように)
  • 先頭にコメントで,題名・氏名・日付を書くこと
ヒント 題材の例:時間割,好きな曲のランキング,星座の星の位置, 町の地図,音の高さの並び(階段状の折れ線),身長の記録. リストの中身を書き換えるだけで別の絵になるように作れたら大成功です. 動かしたければ ontimer を足してください.

まとめ

  • 同じ種類のデータが増えたら,変数を増やすのではなくリストにまとめる
  • リストは [ ] で作り,添字は 0 から.最後の添字は「個数 − 1」で,-1 と書いても取れる.
  • len() で個数.個数をプログラムに直接書かないのがコツ.
  • append で伸ばし,popremove で縮める.
  • for x in リスト が基本.何番目かが要るとき・書き換えたいとき・2 つのリストを合わせるときはfor i in range(len(リスト))
  • 色・長さ・座標,そしてかめ自身もリストに入る.入れてしまえば,何個あっても命令は 1 つで済む.
  • summaxmin・スライス・リストのリストも使える.
  • 合計する・数える・探す・いちばんを見つけるは,どれも「箱を先に用意して,繰り返しの中で更新する」同じ形.

次の回では,このリストを使ってアルゴリズムを組み立てます. 「探す」「並べ替える」を,sorted に頼らずに自分の手で書いてみます. コンピュータが何をしているのかが,はっきり見えるようになります.