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

Python の大事な文法

最終回.ここまでを見わたして,足りないところを埋めます.

最終回です.第 2 章でかめに fd(100) と命令したところから始まって, 変数・条件・繰り返し・関数・リスト・辞書と,ずいぶん遠くまで来ました. もう「やりたいことを手順に分解して,プログラムとして書く」ことが一通りできます.

今回は,ここまでの総まとめとして Python の文法を見わたします. ここまでは,その章に必要な分だけを説明してきました. そのせいで説明しそびれたまま便利なものがいくつも残っています. breakandor,文字列の加工, 書式をそろえた表示,入力の失敗への備え— どれも知っていれば,これから書くプログラムがぐっと楽になるものばかりです.

各項目は短い例と,その場で動かせるコードで進めます. 長い理屈は書きません.実際に動かして,手ざわりを確かめてください. 最後に,この教材では扱わなかったことを正直に挙げて, 次に何を学べばよいかの道しるべを置きます.

この章でできるようになること
  • breakcontinue で繰り返しを制御できる
  • 何回で終わるか分からない繰り返しを,while か「上限つきの forbreak」で書ける
  • notandor で条件を組み立てられる
  • 空のリスト・空の文字列・0 が偽になることを知り,if a: の意味がわかる
  • innot in と,0 <= x < 100 のような連鎖比較が書ける
  • 文字列を切る・つなぐ・置きかえる・区切る,といった加工ができる
  • f-string で,小数のけた数や幅をそろえて表示できる
  • a, b = b, a と,関数から複数の値を返す書き方が使える
  • Noneis None の意味がわかる
  • tryexcept で,入力の失敗に備えられる
  • import の 3 つの書き方を使い分けられる
  • この教材で扱わなかったことを知り,次に何を学べばよいかがわかる

20.1 繰り返しの制御 — break と continue

for の繰り返しは,ふつう最後まで回りきります. 途中でやめたいときと, その章だけ飛ばしたいときの書き方があります.

20.1.1 break — その場でやめる

break を実行すると,その場で繰り返しから抜けます. 「見つかったら,もう探さなくてよい」ときに使います. 第 17 章の線形探索で一度使いました.

break
for i in range(10):
    if i == 4:
        break          # ここで for から抜ける
    print(i)           # 0 1 2 3 だけが出る

20.1.2 continue — この章だけ飛ばす

continue は,繰り返しを抜けるのではなく その章の残りを飛ばして次の回へ進みます. 「この場合は何もしない」を短く書けます.

continue
for i in range(6):
    if i % 2 == 0:
        continue       # 偶数のときは下を飛ばす
    print(i)           # 1 3 5 だけが出る
breakcontinue
何をする繰り返しを終わらせる次の回へ進む
そのあとfor次の行for先頭へ戻る
よく使う場面探しものが見つかった/条件を満たしたのでもう用がないこの値は対象外なので飛ばしたい

20.1.3 break を使わない書き方もある

break は「入口ひとつ・出口ひとつ」というプログラムの作法をくずします. 使いすぎると,どこで抜けるのかが読みにくくなります. 旗(フラグ)の変数を使えば,break なしで同じことが書けます.

2 通りの書き方
# break を使う書き方
for x in a:
    if x == sagasu:
        mitsuketa = True
        break

# 旗の変数を使う書き方(break なし)
mitsuketa = False
for x in a:
    if x == sagasu:
        mitsuketa = True
どちらがよいか 旗を使う書き方は,見つかったあとも最後まで回り続けます. データが多いときは break のほうが速いです. 読みやすさと速さのどちらを取るかという話であって, どちらかが絶対に正しいわけではありません.
break_continue.py
# break:4 になったら繰り返しをやめる
for i in range(10):
    if i == 4:
        break
    print("break の例", i)

print("---")

# continue:偶数の回は飛ばす
for i in range(6):
    if i % 2 == 0:
        continue
    print("continue の例", i)

print("---")

# 実用:リストから探して,見つかったらやめる
a = [14, 8, 23, 5, 42, 16]
sagasu = 23

basho = -1
for i, x in enumerate(a):
    print(i, "番目の", x, "とくらべる")
    if x == sagasu:
        basho = i
        break

if basho >= 0:
    print(sagasu, "は", basho, "番目にありました")
else:
    print(sagasu, "はありませんでした")
効くのは内側 1 つだけ breakcontinue が効くのは, いちばん内側の繰り返し 1 つだけです. 二重の for の内側で break しても, 外側の for は続きます.

20.1.4 何回で終わるかわからないとき

for回数が決まっているときの道具でした. ところが,世の中には「何回やれば終わるのか,やってみないと分からない」仕事があります. たとえば「1 円が毎日 2 倍になるとして,1 億円を超えるのは何日目か」. 答えが分かっていれば for で書けますが, 答えを知りたくて計算しているのですから,回数は書けません.

書き方は 2 つあります. 条件で回す while(第 17 章で, カードを 1 枚ずつ移すときに使いました)と, 多めの回数で回しておいて break で抜ける for です.

baibai.py
# 1 円が毎日 2 倍になる.1 億円を超えるのは何日目?

# 書き方 A:while で,条件が成り立つあいだ回す
okane = 1
hi = 0

while okane <= 100000000:
    hi = hi + 1
    okane = okane * 2

print("A:", hi, "日目に", okane, "円")

print("---")

# 書き方 B:多めに回しておいて,超えたら break
okane = 1

for hi in range(1, 101):        # 100 日もあれば足りるだろう,という上限
    okane = okane * 2
    if okane > 100000000:
        print("B:", hi, "日目に", okane, "円")
        break

どちらでも同じ答えが出ます. while のほうが素直ですが, 条件の書き方をまちがえると終わらなくなるのが怖いところです. forbreak の組み合わせなら, たとえ break の条件をまちがえても 上限の回数で必ず止まります

while True: は使わない ほかの入門書では,ここで while True:(いつまでも回す)と書いて break で抜ける,というやり方を教えていることがあります. この教材ではその書き方は使えません. プログラムはブラウザの中で動いているので,止まらなくなると画面ごと固まってしまいます. 必ず終わる条件を書くか, for に多めの上限を付けて break するか, どちらかにしてください.

タートルでも同じことが起きます. 「画面からはみ出すまで進み続ける」のは,何歩で終わるか分からない仕事です. xcor()ycor()いまの場所を自分で確かめて, はしまで来たら break で止めます.

spiral_break.py
from turtle import *

ht()
speed(0)
pensize(3)
pencolor("#3498db")

nagasa = 6

for i in range(60):          # 60 回は「多めに見積もった上限」
    if abs(xcor()) > 250 or abs(ycor()) > 180:
        print(i, "歩目で画面のはしに来たので,ここでやめます")
        break
    fd(nagasa)
    lt(144)                  # 144 度ずつ曲がると星のような形になる
    nagasa = nagasa * 1.3    # 1 歩ごとに 1.3 倍ずつ長くなる

print("止めなければ,次は", round(nagasa), "も進むところでした")

done()
図 20.1 1 歩ごとに 1.3 倍ずつ長くなるかめ.何歩で画面のはしに届くかは分からないので,上限つきの forbreak で止めている.
abs() — 絶対値 abs(x)絶対値,つまり符号を取り払った値です. abs(-250)250 になります. abs(xcor()) > 250 と書けば, 「右へ行きすぎ」と「左へ行きすぎ」を1 つの条件でまとめて調べられます. nagasa の増える割合(1.3)を変えると, 止まるまでの歩数が変わります.試してみてください.
虫食い虫食い 20-A 合格者を探す

点数のリストから,最初に 80 点以上を取った人を探します. また,0 点の人は集計から飛ばします____ を埋めてください.

fill20_loop.py
# 最初の 80 点以上を探す/0 点は数えない

namae = ["あかり", "けんた", "ゆうき", "みさき", "そうた"]
ten = [65, 0, 92, 88, 51]

# (1) 最初に 80 点以上を取った人を探す(見つかったらやめる)
mitsuketa = ""
for n, t in zip(namae, ten):
    print(n, "は", t, "点")
    if t >= 80:
        mitsuketa = n
        ____
print("最初の 80 点以上は", mitsuketa, "さん")

print("---")

# (2) 0 点の人を飛ばして平均を出す
gokei = 0
kazu = 0
for t in ten:
    if t == 0:
        ____          # この章は飛ばす
    gokei = gokei + t
    kazu = kazu + 1
print(kazu, "人の平均は", gokei / ____)

20.2 真偽値と論理演算子

if のうしろに書く条件は,最後には True(真)か False(偽)の どちらかになります.この 2 つの値を真偽値といいます.

20.2.1 not・and・or — 条件を組み立てる

書き方意味使いどころの例
not AA をひっくり返す.not TrueFalse「ゲーム中でなければ操作を受け付けない」
A and B両方とも成り立つとき「18 歳以上かつ学生」
A or Bどちらか一方でも成り立つとき「左の壁または右の壁に当たった」

not playingplaying == False と同じ意味です. どちらでもかまいませんが,not のほうが短く,英語の文として読めます.

かっこを惜しまない andor が混ざるときは, かっこを付けて意図をはっきりさせてください. a or b and ca or (b and c) の意味ですが, 読む人(とくに数日後の自分)は迷います. 迷ったらかっこ.付けすぎて悪いことは何もありません.

20.2.2 空のリスト・空の文字列・0 は「偽」

Python では,TrueFalse 以外のものも if の条件に書けます. そのとき「空っぽ」「ゼロ」は偽として扱われます.

真偽おぼえ方
00.0ゼロは偽
0 以外の数
""(空の文字列)空っぽは偽
"あ" など中身のある文字列
[]{}set()空の入れ物も空っぽ
中身のあるリスト・辞書・集合
None「何も無い」も偽

これを知っていると,条件が短く書けます.

空かどうかの書き方
# 長い書き方
if len(a) > 0:
    print("中身があります")

# 短い書き方(同じ意味)
if a:
    print("中身があります")

# 空かどうか
if not a:
    print("からっぽです")
短ければよいわけではない ただし,数を調べたいときは省略しないほうがよいことが多いです. if kazu: は「0 でなければ」という意味になりますが, if kazu > 0: と書いたほうが,読む人には意図が伝わります. 短さより,読んだときに意味が分かることを優先してください.

20.2.3 in / not in と,連鎖比較

in は「入っているか」を調べる書き方でした. 否定は not in と書きます(not x in a ではありません).

もう 1 つ,Python ならではの便利な書き方があります. 比較を 2 つつなげて書けるのです. 数学と同じ見た目になるので,範囲の判定がとても読みやすくなります.

書き方意味他の言語では
0 <= x < 100x が 0 以上 100 未満0 <= x and x < 100 と 2 つに分けて書く
a < b < ca より b が大きく,b より c が大きい同じく 2 つに分ける
x in a / x not in a入っている/入っていない
logic.py
# not / and / or
playing = False
if not playing:
    print("ゲームは止まっています")

x = 120
y = 40
if x > 100 and y > 30:
    print("and:2 つとも成り立つ")
if x > 500 or y > 30:
    print("or:どちらか一方でも成り立つ")

print("---")

# 空っぽは偽
a = []
b = [1, 2, 3]
namae = ""

if not a:
    print("a はからっぽ")
if b:
    print("b には", len(b), "個入っている")
if not namae:
    print("名前が入力されていません")

print(bool(0), bool(5), bool(""), bool("あ"), bool([]), bool([0]))

print("---")

# in / not in
kudamono = ["りんご", "みかん"]
print("りんご" in kudamono)
print("すいか" not in kudamono)
print("と" in "たーとる")          # 文字列の中にもある

print("---")

# 連鎖比較
ten = 85
if 80 <= ten < 90:
    print("A 判定")

for t in [-5, 0, 50, 100, 120]:
    if 0 <= t <= 100:
        print(t, "は正しい点数")
    else:
        print(t, "はありえない点数")
虫食い虫食い 20-B 入場できるかを判定する

年齢と持ち物から,入場できるかどうかを判定します. ____ を埋めてください. 「かつ」「または」「でなければ」を, andornot に置きかえます.

fill20_logic.py
# 入場判定

nenrei = 17
chiketto = True
motimono = ["かばん", "みずとう"]
kinshi = ["はもの", "かさ"]

# (1) 年齢が 6 以上 18 未満なら「学生料金」(連鎖比較で書く)
if ____ <= nenrei ____ 18:
    print("学生料金です")
else:
    print("おとな料金です")

# (2) チケットを持っていて,かつ 6 歳以上なら入場できる
if chiketto ____ nenrei >= 6:
    print("入場できます")

# (3) チケットを持っていなければ,買ってもらう
if ____ chiketto:
    print("チケットを買ってください")

# (4) 禁止されているものを持っていないか調べる
dame = False
for m in motimono:
    if m ____ kinshi:
        dame = True
if not dame:
    print("持ち物は問題ありません")

# (5) 持ち物がからっぽなら,そう言う(空のリストは偽)
if ____ motimono:
    print("手ぶらですね")

20.3 文字列をあつかう

第 9 章の CUI プログラムで input() を使いました. 受け取るのはいつも文字列です. 文字列を切ったり,つないだり,区切ったりできると,作れるものが広がります.

20.3.1 文字列はリストに似ている

文字列は文字が並んだものなので, リストと同じ感覚であつかえます. len も,添字も,スライスも,in もそのまま使えます.

書き方意味
len(s)文字数
s[0] / s[-1]最初の文字/最後の文字
s[0:3] / s[::-1]先頭 3 文字/逆順(第 19 章のスライス)
s + tつなぐ
s * 33 回くり返す."-" * 30 は区切り線に便利
"る" in sその文字(や語)が入っているか
str(n) / int(s) / float(s)数と文字列を行き来する
文字列は変えられない 文字列はあとから変えられません(タプルと同じです). s[0] = "あ" はエラーになります. 変えたいときは,s = s.replace(…) のように 新しい文字列を作って入れ直します

20.3.2 よく使うメソッド

書き方すること
s.upper() / s.lower()大文字に/小文字に"abc".upper()"ABC"
s.strip()前後の空白や改行を取り除く入力の後始末にほぼ必須
s.split(区切り)区切ってリストにする"a,b,c".split(",")["a", "b", "c"]
区切り.join(リスト)リストをつなげて文字列にする",".join(["a", "b"])"a,b"
s.replace(前, 後)置きかえる(全部)"あかあか".replace("あか", "しろ")
s.find(x)x が何番目にあるか.無ければ -1"たーとる".find("と")2
s.count(x)x がいくつ入っているか
s.startswith(x)x で始まるか
string.py
s = "たーとるぐらふぃっくす"

print(len(s))
print(s[0], s[-1])
print(s[0:3])
print(s[::-1])
print(s + "!")
print("-" * 24)
print("る" in s)

print("---")

t = "  Hello, Turtle World  "
print("[" + t + "]")
print("[" + t.strip() + "]")          # 前後の空白を取る
print(t.strip().upper())
print(t.strip().lower())
print(t.strip().replace("Turtle", "Python"))

print("---")

# 区切る → リスト/つなぐ → 文字列
gyo = "あかり,けんた,ゆうき"
namae = gyo.split(",")
print(namae)
print(" と ".join(namae))
print("/".join(namae))

print("---")

print("たーとる".find("と"))     # 2 番目にある
print("たーとる".find("ね"))     # 無いので -1
print("あかあおあか".count("あか"))
print("turtle.py".startswith("turtle"))

# 数と文字列の行き来
print(int("42") + 1)
print(str(42) + "点")
print(float("3.5") * 2)

20.3.3 f-string — 表示をきれいにそろえる

これまで print("平均は", heikin, "点") のように, カンマで区切って並べてきました. f-string(エフストリング)を使うと, 文字列の中に { } で値を埋め込めます.

f-string
namae = "あかり"
ten = 87.5

# これまでの書き方
print(namae, "さんは", ten, "点です")

# f-string(先頭に f を付けて,{ } の中に変数を書く)
print(f"{namae}さんは{ten}点です")

本当に便利なのは,{ } の中でけた数や幅を指定できることです. {値:書式} の形で書きます.

書き方意味結果の例
{x:.2f}小数点以下 2 けたに丸める3.14
{x:.0f}小数点以下を出さない3
{x:5}5 文字ぶんの幅を取る(数は右寄せ)   42
{x:>8} / {x:<8} / {x:^8}右寄せ/左寄せ/中央ぞろえ
{n:03d}0 を詰めて 3 けたにする007
{n:,}3 けたごとにカンマを入れる1,234,567
{a + b}中で計算もできる
fstring.py
namae = "あかり"
ten = 87.5
kazu = 1234567

print(f"{namae}さんは {ten} 点です")
print(f"1 + 2 = {1 + 2}")

print("---")

# 小数のけた数
heikin = 72.66666
print(f"平均は {heikin} 点")
print(f"平均は {heikin:.2f} 点")
print(f"平均は {heikin:.1f} 点")
print(f"平均は {heikin:.0f} 点")

print("---")

# けたをそろえる(表になる)
seiseki = [("あかり", 78, 158.2), ("けんた", 92, 172.5),
           ("ゆうき", 6, 165.0), ("みさき", 100, 149.8)]

print(f"{'名前':<8}{'点数':>6}{'身長':>9}")
print("-" * 26)
for n, t, h in seiseki:
    print(f"{n:<8}{t:>6}{h:>9.1f}")

print("---")

print(f"{7:03d} 番")
print(f"{kazu:,} 円")
print(f"[{'あか':>6}] [{'あか':<6}] [{'あか':^6}]")
日本語の幅 幅の指定は文字数で数えます. 日本語は 1 文字が半角 2 文字ぶんの幅で表示されるので, 日本語と半角が混ざると,画面の上ではきれいにそろわないことがあります. 数字だけの表なら,きちんとそろいます.

タートルの write とも相性がよい書き方です. str()+ を並べずに済むので, 画面に文字を書くプログラムがぐっと読みやすくなります.

write_fstring.py
from turtle import *

ht()

seiseki = [("あかり", 78), ("けんた", 92), ("ゆうき", 61), ("みさき", 55)]

ten = [t for n, t in seiseki]
heikin = sum(ten) / len(ten)

pu()
goto(-240, 160)
pencolor("black")
write(f"{len(seiseki)} 人の成績(平均 {heikin:.1f} 点)",
      font=("Arial", 20, "normal"))

y = 100
for jun, kumi in enumerate(seiseki):
    namae = kumi[0]
    t = kumi[1]
    pu()
    goto(-240, y)
    if t >= 60:
        pencolor("navy")
    else:
        pencolor("crimson")
    write(f"{jun + 1} 位 {namae}", font=("Arial", 20, "normal"))
    goto(80, y)
    write(f"{t:>3} 点", font=("Arial", 20, "normal"))
    y = y - 55

done()
4 人の成績(平均 71.5 点)1 位 あかり 78 点2 位 けんた 92 点3 位 ゆうき 61 点4 位 みさき 55 点
図 20.2 f-string で書式をそろえて write したもの.
虫食い虫食い 20-C 成績表をきれいに表示する

入力された名前と点数から,成績表を作って画面に描きます. ____ を埋めてください. 文字列を区切るところと,f-string の書式がポイントです.

fill20_fstring.py
from turtle import *

ht()

# 「名前:点数」をカンマ区切りで受け取る
gyo = input("例)あかり:78,けんた:92 のように入力:")

# (1) カンマで区切ってリストにする
kumi = gyo.____(",")
print(kumi)

seiseki = []
for k in kumi:
    # (2) コロンで区切って,名前と点数に分ける
    namae, ten = k.____(":")
    # (3) 点数は文字列なので,数に直す
    seiseki.append((namae.strip(), ____(ten)))

print(seiseki)

# (4) 平均を小数点以下 1 けたで表示する
ten = [t for n, t in seiseki]
heikin = sum(ten) / len(ten)
print(f"平均は {heikin:____} 点")

# (5) 画面に書く
y = 130
for namae, t in seiseki:
    pu()
    goto(-200, y)
    write(f"{namae} {t:>4} 点", font=("Arial", 22, "normal"))
    y = y - 55

pu()
goto(-200, y - 20)
write(f"平均 {heikin:.1f} 点", font=("Arial", 22, "normal"))

done()

20.4 値のやりとり — 複数代入・複数の戻り値・None

20.4.1 複数代入 — 一度に 2 つ入れる

Python では,カンマで並べて一度に代入できます. 第 17 章で使った a, b = b, a(入れ替え)が代表です.

複数代入
x, y = 100, 50          # 一度に 2 つ
a, b = b, a             # 入れ替え.作業用の変数が要らない
namae, ten = ("あかり", 78)   # タプルをほどく
なぜ入れ替わるのか a, b = b, a がうまくいくのは, 右側を先に全部計算してから左側へ入れるからです. a = bb = a を 2 行に分けて書くと, 1 行目で a の元の値が消えてしまい,入れ替わりません.

20.4.2 関数から 2 つ以上の値を返す

第 14 章で return を習いました. じつはカンマで並べれば,いくつでも返せます. 返ってくるのはタプル(第 19 章)なので, 受け取るときも複数代入でほどけます.

multi_return.py
def saidai_saisho(a):
    """最大値と最小値を両方返す"""
    return max(a), min(a)


def wa_to_sa(x, y):
    return x + y, x - y


ten = [72, 95, 61, 88, 40]

ue, shita = saidai_saisho(ten)
print("最高", ue, " 最低", shita)

wa, sa = wa_to_sa(10, 4)
print("和", wa, " 差", sa)

# 受け取らずにそのまま見ると,タプルになっている
print(saidai_saisho(ten))

print("---")

# 複数代入・入れ替え
x, y = 100, 50
print(x, y)
x, y = y, x
print(x, y)

20.4.3 None — 「まだ何も無い」を表す値

None は,「値が無い」ことを表す特別な値です. 0 でも空文字列でもありません.「まだ決まっていない」という印です.

  • return を書かない関数は,None を返します
  • d.get(k) は,キーが無ければ None を返します(第 18 章)
  • a.sort()None を返します.b = a.sort() と書いて失敗するのはこのためです(第 17 章)

None かどうかを調べるときは, == None ではなく is None と書きます. 「同じ値か」ではなく「まさにそれか」を聞いているからです.

is None / is not None
kotae = None

if kotae is None:
    print("まだ答えが決まっていません")

if kotae is not None:
    print("答えは", kotae)
偽と None は違う None は偽として扱われるので if not kotae: とも書けますが, 0 や空文字列も偽なので,区別が付きません. 「0 が入っているのか,まだ何も入っていないのか」を分けたいときは, 必ず is None を使ってください.

20.5 失敗に備える — try と except

int(input()) は,数を入力してもらう定番の書き方でした. しかし利用者が「ごじゅう」と打ったら,どうなるでしょうか.

文字を入れられると落ちる
n = int(input("数を入れてください:"))

ValueError が出て,プログラムはそこで止まります. このように,実行中に起きる異常を例外(れいがい)といいます. 例外が起きても止まらないようにする書き方が tryexcept です.

try / except の形
try:
    あぶないかもしれない処理
except 例外の種類:
    失敗したときにやること

try: の中で例外が起きると,そこで中断して except: の中へ飛びます.起きなければ except は素通りします.

例外の名前起きる場面
ValueErrorint("abc") のように,形が合わない値を渡したとき
ZeroDivisionError0 で割ったとき
IndexErrora[10] のように,無い番号を指したとき
KeyError辞書に無いキーを d[k] で引いたとき
TypeError"a" + 1 のように,種類の合わないものを混ぜたとき
NameError無い名前を使ったとき(打ち間違いが多い)
try_input.py
# 数を 3 回まで入力し直せるようにする

n = None

for i in range(3):
    kotae = input("数を入れてください:")
    try:
        n = int(kotae)
        break                       # うまくいったので繰り返しをやめる
    except ValueError:
        print(f"「{kotae}」は数ではありません.あと {2 - i} 回")

if n is None:
    print("数が受け取れませんでした.0 として続けます")
    n = 0

print(f"{n} の 2 倍は {n * 2} です")

# 0 で割る失敗にも備える
try:
    print(100 / n)
except ZeroDivisionError:
    print("0 では割れません")
except: だけで受けない except: と種類を書かずに全部受け止めることもできますが, やめてください. 打ち間違いによる NameError まで握りつぶしてしまい, 「なぜか動かないが,エラーも出ない」という最悪の状態になります. 受け止める例外の種類は必ず書く.
try の出番 例外は「使わずに済むならそのほうがよい」ものです. d.get(k, 0)if k in d: で防げるなら,そちらを使ってください. try の出番は,防ぎようがない失敗— 人間の入力,ファイルの読み込み,通信—に備えるときです.
虫食い虫食い 20-D 安全な BMI 計算

身長と体重を入力して BMI を計算します. 数でないものを入れられても止まらないようにしてください. ____ を埋めてください.

fill20_bmi.py
# 安全な BMI 計算

shincho = None
taiju = None

# (1) 身長(cm)
s = input("身長を cm で入れてください:")
____:
    shincho = float(s) / 100
____ ValueError:
    print(f"「{s}」は数ではありません")

# (2) 体重(kg)
t = input("体重を kg で入れてください:")
try:
    taiju = float(t)
except ____:
    print(f"「{t}」は数ではありません")

# (3) どちらかが受け取れていなければ,ここで終わる
if shincho ____ None or taiju is None:
    print("計算できませんでした")
else:
    bmi = taiju / (shincho * shincho)
    # (4) 小数点以下 1 けたで表示する
    print(f"BMI は {bmi:____} です")
    if bmi < 18.5:
        print("やせ型です")
    elif ____ <= bmi < 25:
        print("標準です")
    else:
        print("肥満型です")

20.6 import の 3 つの書き方

printlensorted は, 何も書かなくても使えました(組み込み関数といいます). 一方,random.randint のように 使う前に道具箱を開けなければならないものがあります. これが標準ライブラリで,Python には 200 以上の箱が付いてきます.

道具箱よく使うもの何に使うか
randomrandint(a, b)choice(a)shuffle(a)seed(n)でたらめな数や選択.第 3 章から使っています
mathsqrt(x)pisin(x)cos(x)radians(d)平方根や三角関数.斜めの長さや円の計算
timetime()いまの時刻を秒で返す.差をとって「かかった時間」を測る
turtlefdltgotoこの教材でずっと使ってきた箱

箱の開け方は 3 通りあります.結果は似ていますが,意味が違います.

書き方呼び出し方性質と使いどころ
import randomrandom.randint(1, 6)箱ごと持ってくる.どの箱の道具かが一目でわかる.ふだんはこれ
from random import randintrandint(1, 6)使うものだけ名前を借りる.短く書けるが,出どころが見えなくなる
from random import *randint(1, 6)箱の中身を全部借りる.from turtle import * がこれ

import は,プログラムのいちばん上に書くのが決まりです. 先頭のコメントのすぐ下,ほかの処理より前に並べます.

import3.py
# 道具箱を 3 通りの書き方で開けてみる
import math
import random
from math import sqrt          # sqrt だけ名前を借りる

print(math.pi)
print(math.sqrt(2))
print(sqrt(2))                 # 借りたので math. が要らない

print(math.floor(3.7), math.ceil(3.2))    # 切り捨て・切り上げ
print(f"{math.sin(math.radians(30)):.3f}")

random.seed(1)                 # 毎回同じ結果にしたいときの「種」
print(random.randint(1, 6))
print(random.choice(["赤", "青", "黄"]))

a = [1, 2, 3, 4, 5]
random.shuffle(a)              # かきまぜる(a 自身が変わる)
print(a)
from ○○ import * は控えめに from ○○ import * は,箱の中の名前を全部そのまま持ってきます. 箱を 2 つ開けて同じ名前の道具があると, あとから開けたほうで上書きされてしまいます. 自分で作った変数や関数が消されることもあります. この教材で from turtle import * だけ特別に使っているのは, fdlt をいちいち turtle.fd と書くのが 大変だからです.それ以外の箱は import random のほうを使ってください.
よくあるエラー NameError: name 'sqrt' is not defined と出たら, たいてい import の書き忘れです. math.sqrt と書くなら import mathsqrt と書くなら from math import sqrt が必要です.
虫食い虫食い 20-E さいころを振って記録する

さいころを 60 回振り,出た目を数えて表示します. 今回習ったことを寄せ集めた総合問題です. ____ を埋めてください.

fill20_dice.py
# さいころを 60 回振る

____ random

random.seed(3)                 # 毎回同じ結果にする

kekka = []
for i in range(60):
    kekka.append(random.randint(1, ____))

# (1) 目ごとの回数を数える(辞書)
kazu = {}
for me in kekka:
    kazu[me] = kazu.get(me, 0) + 1

# (2) 1 の目が 1 回でも出たか
if 1 ____ kekka:
    print("1 の目は出ました")

# (3) けたをそろえて表示する
for me in sorted(kazu):
    n = kazu[me]
    wariai = n / len(kekka) * 100
    bar = "■" * n
    print(f"{me} の目:{n:>3} 回({wariai:____}%){bar}")

# (4) いちばん多かった目(値で比べて並べ替える)
def kaisu(kv):
    return kv[____]

narabi = sorted(kazu.items(), key=kaisu, reverse=True)
print(f"いちばん多かったのは {narabi[0][0]} の目で {narabi[0][1]} 回")

20.7 この教材では扱わないこと

この教材では Python のすべてを扱ったわけではありません. あえて扱わなかったものを,正直に挙げておきます. 「知らないことがある」と知っていることは,それ自体が力になります.

扱わなかったことどんなものかいつ必要になるか
クラス定義
class
データと処理をひとまとめにした新しい種類を,自分で作る書き方.この教材で使った Turtle() がまさにそれで,使う側だけは何度も経験していますプログラムが大きくなったとき.「オブジェクト指向」という言葉はここから始まります
ファイル入出力
open
データをファイルに保存し,読み戻す書き方.この画面はブラウザの中で動いているので扱えません.第 1 章で入れた手元の Python なら使えますプログラムを閉じてもデータを残したいとき.成績表,設定,ゲームのセーブデータ
外部ライブラリ
pip install
世界中の人が作って公開している道具箱を,あとから足して使う仕組み.表計算の pandas,グラフの matplotlib,数値計算の numpy,通信の requests など実務や研究で Python を使うとき.むしろここからが Python の本領です
その他正規表現,再帰(第 15 章),並行処理,テスト,型ヒント,while True: による本格的なループ(ブラウザでは固まるため)必要になったときに,1 つずつ

20.7.1 次に何を学べばよいか

道しるべを 4 つ置いておきます.順番に迷ったら,上から順でかまいません.

  1. 自分のパソコンで動かす.第 1 章でやったとおり,VS Code と Python を手元に用意してください.ブラウザの制限が無くなり,while True: もファイル操作も使えます.これがいちばん大きな一歩です.
  2. 公式チュートリアルを読む.docs.python.org/ja/3/tutorial/ に日本語版があります.この教材で習ったことがひととおり出てくるので,復習しながら,足りないところを埋められます.クラス定義もファイル入出力も,ここに書いてあります.
  3. 作りたいものを 1 つ決める.文法を全部覚えてから作ろうとすると,たいてい始まりません.作りたいものを決めて,必要になった文法だけを調べる.これがいちばん早く上達するやり方です.
  4. 2 年次以降の科目につなげる.「データ構造とアルゴリズム」では,第 17 章・第 19 章で触れた話をきちんと学びます.ほかの言語を習うときは,「Python ではこう書いた」と対応づけながら読むと速いです.
この教材で身につけてほしかったこと 最後に 1 つだけ. プログラミングで本当に必要なのは,命令を暗記していることではありません. やりたいことを手順に分解できることと, 思いどおりに動かないときに原因を突きとめられることです. この 2 つは,第 2 章でかめに fd(100) と命令した日から, ずっと練習してきたことです. 使う言語が変わっても,この力はそのまま持っていけます.

20.8 この章で出てきた書き方

書き方意味
break繰り返しをその場でやめる
continueその章の残りを飛ばして次の回へ
while 条件:条件が成り立つあいだ繰り返す.回数が決まっていないとき
abs(x)絶対値.符号を取り払った値
not A真偽をひっくり返す
A and B / A or B両方/どちらか一方でも
if a:a が空でなければ.空のリスト・空の文字列・0・None は偽
bool(x)x が真か偽かを確かめる
x in a / x not in a入っている/入っていない
0 <= x < 100連鎖比較.範囲の判定が数学と同じ見た目で書ける
len(s) / s[0] / s[0:3]文字列の長さ/1 文字/切り出し
s + t / s * 3つなぐ/くり返す
s.upper() / s.lower()大文字に/小文字に
s.strip()前後の空白・改行を取り除く
s.split(区切り)区切ってリストにする
区切り.join(リスト)リストをつなげて文字列にする
s.replace(前, 後)置きかえる
s.find(x)何番目にあるか.無ければ -1
f"{x}"f-string.文字列の中に値を埋め込む
f"{x:.2f}"小数点以下 2 けた
f"{x:>6}"6 文字ぶんの幅で右寄せ(< 左,^ 中央)
f"{n:03d}" / f"{n:,}"0 詰め/3 けた区切り
a, b = b, a2 つの値を入れ替える
return x, y2 つの値を返す(タプルになる)
None「値が無い」ことを表す特別な値
x is None / x is not NoneNone かどうかを調べる(== None とは書かない)
try:except ValueError:失敗しても止まらないようにする
import random道具箱ごと開ける.random.randint(1, 6)
from math import sqrt道具を 1 つ借りる.sqrt(2)
from turtle import *箱の中身を全部借りる

演習

出発点のプログラムを「▶ この演習を開く」で右側に読み込み, それを発展させて作品にしてください. input() を使う演習には,右コンソールの入力行に あらかじめ値を入れてあります.書き換えて試してください. できあがったら「⤓ 保存」でファイルに保存して,手元に残しておきましょう.

演習演習 20-1 こわれない計算プログラム

何を入力されても止まらない計算プログラムを作ります. 出発点は,まったく備えのない状態です.実際に文字を入れて落としてみてください.

  1. tryexcept ValueError で,数でないものを入れられても止まらないようにする.
  2. 数でなかったら入力し直させるforbreakwhile True: は使えません).
  3. 0 で割る失敗(ZeroDivisionError)にも備える.
  4. 受け取れた値がないときは None のままにしておき,is None で判定して,そのときの動きを決める.
  5. 余裕があれば,範囲の判定も入れる.点数なら 0 <= n <= 100 でないときは入れ直させる.
ヒント 入力し直させるときは,コンソールでもう一度打てば 何回ぶんでも試せます.わざと変な値を並べて,動きを確かめてください.
演習演習 20-2 文字列であそぶ

入力された文を加工して,画面に描きます. 文字列のメソッドとスライスの練習です.

  1. 入力された文の文字数を表示する.
  2. 逆さまにしたものを表示する(s[::-1]).
  3. カンマで区切ってリストにし,別の記号でつなぎ直して表示する(splitjoin).
  4. 指定した言葉を別の言葉に置きかえて表示する(replace).
  5. 加工した結果を,タートルの write で画面に縦に並べる.色や文字の大きさも変えること.
  6. 余裕があれば,回文かどうかを判定する(s == s[::-1]).
演習演習 20-3 条件で仕分けるプログラム

andornot・連鎖比較・ in を使って,データを仕分けます.

  1. 点数のリストを,A(80 以上)・B(60 以上 80 未満)・C(60 未満)の 3 つに仕分ける.連鎖比較 60 <= t < 80 を使うこと.
  2. ありえない点数(0 未満や 100 より大きい)が混じっていたら,continue で飛ばして,飛ばした個数を数える.
  3. 仕分けた結果を,3 色の棒グラフか円の大きさで描く.
  4. anyall を使って「1 人でも満点がいるか」「全員合格か」を表示する.
  5. 余裕があれば,名前つきのデータ(タプルのリスト)にして,A 判定の人の名前を内包表記で取り出して表示する.
演習演習 20-4 書式をそろえた一覧表

f-string の書式を使って,けたのそろった表を作ります. コンソールとタートル画面の両方に出してください.

  1. 商品名・個数・単価のデータから,小計を計算する.
  2. f"{x:>8}" などを使って,数の右はしがそろった表をコンソールに表示する.見出しの行と区切り線("-" * 40)も入れること.
  3. 金額は f"{x:,}"3 けた区切りにする.
  4. 合計と平均も出す.平均は小数点以下 1 けた(:.1f).
  5. 同じ表を,タートルの write で画面にも描く.
  6. 余裕があれば,小計の高い順に並べ替えてから表示する(第 19 章の key=).
ヒント write で表を描くときは,等幅でないので 列ごとに x 座標を変えて書くほうがきれいにそろいます.
自由演習 20-5 自由制作:総まとめ

最後の課題です.ここまでに習ったことを使って,好きなものを作ってください. テーマは自由です.絵でも,ゲームでも,計算でも,データの集計でもかまいません.

  • 関数(defを 2 つ以上作ること(第 13 章・第 14 章)
  • リスト・辞書・タプル・集合のうち 2 つ以上を使うこと(第 16 章・第 18 章・第 19 章)
  • 繰り返しと条件分岐を使うこと(第 5 章・第 6 章)
  • 今回習ったもの(breakcontinueandornot,文字列の加工,f-string,try)から2 つ以上使うこと
  • 先頭にコメントで,題名・氏名・日付・何をするプログラムかを書くこと
  • 読む人のためのコメントを要所に入れること.「何をしているか」ではなく「なぜそうしているか」を書く
ヒント アイデアが浮かばないときは,これまでの回の演習を 1 つ選んで 作り直すのがおすすめです. 当時より道具が増えているので,ずっと短く,きれいに書けるはずです. 「あのときはこう書いたが,いまならこう書く」という比較そのものが, この半年の成果です.

まとめ

  • break は繰り返しを終わらせ,continue は次の回へ進む.効くのはいちばん内側の繰り返し 1 つだけ.
  • 何回で終わるか分からない繰り返しは,while上限つきの forbreak で書く.while True: は使わない.
  • notandor で条件を組み立てる.混ざるときはかっこを惜しまない.
  • 空のリスト・空の文字列・0・None は偽.だから if a: で「中身があるか」を書ける.
  • 0 <= x < 100 という連鎖比較が書ける.範囲の判定が数学と同じ見た目になる.
  • 文字列はリストに似ている.split で区切り,join でつなぎ,replace で置きかえる.
  • f-string f"{x:.2f}" でけた数や幅をそろえられる.表がきれいになる.
  • a, b = b, areturn x, y.Python は複数の値をまとめてあつかえる.
  • None は「値が無い」印.調べるときは is None
  • tryexcept ValueError で,入力の失敗に備える.受け止める例外の種類は必ず書く
  • import はふだん import random の形で.from ○○ import * は名前がぶつかるので控えめに.

これでおしまいです. 第 2 章で fd(100) と 1 行書いたところから, データを集計して絵にするところまで来ました. ここから先は,作りたいものを決めて,必要な道具を自分で探す番です. 調べ方はもう知っています.行きづまったら,速度を落として,少しずつ書いて, print で覗いてみる.やり方は第 2 章から何も変わりません. よい旅を.