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

変数と計算

数に名前をつけて覚えさせる.1 か所直せば,絵全体が変わります.

前の章のプログラムには,10090 といった数が そのまま何度も書かれていました.絵を少し大きくしたいと思ったら, その 100 を全部探して書き換えなければなりません. 5 か所なら我慢できますが,50 か所ならどうでしょうか. しかも 1 か所でも直し忘れたら,形が崩れます.

今回は変数(へんすう)を習います. 数に名前をつけてコンピュータに覚えさせておき,あとはその名前で呼び出す,という仕組みです. これを使うと,「1 辺の長さ」を 1 か所に書くだけで, 絵全体の大きさをいっぺんに変えられるようになります. さらに,覚えさせた数どうしで計算させたり, 人に入力してもらった数を使ったりできるようになります.

この章でできるようになること
  • 変数に値を覚えさせ,あとからその名前で呼び出せる
  • = が「等しい」ではなく「入れる」であることを説明できる
  • 変数の名前の付け方のきまりがわかり,意味のある名前をつけられる
  • + - * / // % ** を使い分けられる.とくに /// の違いがわかる
  • intfloatstr という 3 つの型を区別できる
  • input() で入力を受け取り,int() で数に直して使える
  • f"…" で,文字と数をまぜて表示できる
  • 入力と結果に言葉と単位を添え,人が使えるプログラムにできる
  • 乱数を使って,実行するたびに変わる絵が描ける
コンソールの入力行のこと 今回から,プログラムがキーボードからの入力を受け取るようになります.
  • 右下の「コンソール」のいちばん下に入力する行があります.
  • プログラムが input() のところまで来ると,そこでいったん止まって 「入力を待っています」と出ます.
  • 入力する行に打ち込んで Enter を押すと,続きが動きます.
  • 聞かれた言葉も,打った内容も,そのままコンソールに残ります.
手元の PC で動かしたときと,同じ感覚で使えます.

3.1 同じ数を何度も書くのはつらい

前の章の「家」のプログラムを思い出してください. 屋根の 3 辺と,かべの 4 辺で,fd(100) が合計 7 回出てきます.

house0.py
from turtle import *

# 屋根を描く
lt(60)
fd(100)
rt(120)
fd(100)
rt(120)
fd(100)

# かべを描く
lt(90)
fd(100)
lt(90)
fd(100)
lt(90)
fd(100)
lt(90)
fd(100)

done()
図 3.1 変数を使っていない家.100 が 7 か所に散らばっている.

この家を1.5 倍にしてみてください,と言われたらどうしますか. 7 か所すべてを 150 に書き換えることになります. さらに「やっぱり 1.2 倍で」と言われたら,また 7 か所です.

直し忘れは必ず起きる このような書き方には,つまらない間違いが必ず起きます. 6 か所だけ直して 1 か所忘れる,という失敗です. 屋根だけが小さい家ができあがり,しかもエラーは出ませんから, 自分で気づくまで直りません. 同じ数が何度も出てきたら,変数の出番だと考えてください.

3.2 変数を使う

3.2.1 変数を使った家

同じ家を,変数を使って書き直します.変わったのは最初の 1 行と, 100 と書いていたところが length になったところだけです.

house1.py
from turtle import *

length = 100      # 1 辺の長さ

# 屋根を描く
lt(60)
fd(length)
rt(120)
fd(length)
rt(120)
fd(length)

# かべを描く
lt(90)
fd(length)
lt(90)
fd(length)
lt(90)
fd(length)
lt(90)
fd(length)

done()
図 3.2 変数 length を使った家.図は length = 100 のとき.

右側で開いて,length = 100100 だけを 60150 に書き換えて実行してみてください. 1 か所直すだけで,家全体の大きさが変わります.

図 3.3 length = 60
図 3.4 length = 100
図 3.5 length = 150

3.2.2 変数は名前のついた箱

コンピュータにはメモリという,数を覚えておく場所があります. 変数とは,そのメモリの一区画に名前をつけて予約したものです. ふつうは「名前の書かれた箱」にたとえます. 箱の中に入っている数のことを値(あたい)といいます.

100length50small90angle
図 3.6 変数は「名前のついた箱」.箱の中身が値.
  • 箱はいくつでも作れます(メモリの許す限り).
  • 1 つの箱には1 つの名前をつけます.
  • 箱の中身はあとから入れ替えられます.だから「変わる数」=変数といいます.
  • 中身を取り出しても,箱の中身は減りません.何度でも読み出せます.

3.2.3 代入 — = は「等しい」ではない

length = 100 という 1 行を代入文といいます. この = は,算数の「等号」ではありません. 「右にあるものを,左の箱に入れなさい」という命令です. 読むときも「length イコール 100」ではなく, 「length に 100 を入れる」と読んでください.

代入文の読み方
length = 100
#  ↑       ↑
#  入れ先   入れるもの

= が命令だと分かると,Python の実行の順番も見えてきます. 代入文は,必ず右side を先に計算してから,左の箱に入れます

順番すること
1=右側を計算して,1 つの値にする(これを評価という)
2できた値を,=左側の箱に入れる
なぜ length / 2 = small は書けないのか だから,左側には箱(変数名)しか書けません100 = lengthlength / 2 = small はエラーになります. 「100 という箱」「length ÷ 2 という箱」は存在しないからです. 覚えておくことはひとつだけです. 代入の左側は入れ物でなければならない

3.2.4 変数を書くと中身に置き換わる

fd(length) と書くと,Python はまず length の箱をのぞき, 中身の 100 を取り出します.そのうえで fd(100) を実行します. この「箱をのぞいて値にする」ことを評価といいます.

書いたもの評価された結果実際に動くこと
fd(length)fd(100)100 歩進む
lt(right_angle)lt(90)左に 90 度回る
print(length)print(100)コンソールに 100 と出る

次のプログラムで,箱の中身が実際に取り出せることを確かめてください.

eval.py
length = 100
angle = 90

print(length)
print(angle)
print(length)     # 何度でも取り出せる
使う前に入れておくこと 箱を作る前に中身を取り出そうとすると,NameError になります. print(length) より前に length = 100 を 書いておかなければなりません.プログラムは上から順に実行されるのでしたね.

実際に失敗させてみましょう.次のプログラムは,順番が入れ替わっているだけです.

undefined.py
print(length)     # ← まだ length という箱は無い
length = 100

1 行目: NameError: name 'length' is not defined と出ます. 「length という名前は知りません」という意味です. 2 行目で作ってはいるのですが,1 行目の時点ではまだ存在していません. 2 行を入れ替えれば動きます.やってみてください.

打ち間違いでも NameError NameError は,第 2 章では命令名の打ち間違いとして出てきました. 今回は変数の打ち間違いでも出ます. length と書くつもりで lenght と打てば, Python にとっては「聞いたことのない名前」なので同じエラーになります. エラーに出ている名前を,自分が書いたつもりの名前と見比べるのが一番速い直し方です.
虫食い虫食い 3-A 変数で正三角形

1 辺の長さを length という変数で決めて,正三角形を描きます. ____ を埋めて,1 辺 130 の正三角形にしてください. fd のかっこの中には数ではなく変数名を書きます.

fill1_triangle.py
from turtle import *

length = ____       # 1 辺の長さを 130 にする

pensize(3)
pencolor("teal")

fd(____)
rt(120)
fd(____)
rt(120)
fd(____)
rt(120)

done()

3.3 変数の名前の付け方

3.3.1 変数はいくつでも作れる

変数は 1 つだけではありません.いくつでも作れます. ただし区別するために,それぞれ違う名前をつけなければなりません. 次のプログラムは,「1 辺の長さ」と「直角」の 2 つを変数にしています.

house2.py
from turtle import *

length = 100          # 1 辺の長さ
right_angle = 90      # 直角

# 屋根を描く
lt(60)
fd(length)
rt(120)
fd(length)
rt(120)
fd(length)

# かべを描く
lt(right_angle)
fd(length)
lt(right_angle)
fd(length)
lt(right_angle)
fd(length)
lt(right_angle)
fd(length)

done()
図 3.7 変数を 2 つ使った家.長さと角度に別々の名前がついている.
名前はコメントの代わりになる right_angle のように名前から意味が読み取れると, プログラムが「ことば」として読めるようになります. lt(right_angle) は「直角ぶん左に回る」と読めます. lt(90) より,やろうとしていることがはっきりします.

3.3.2 名前に使ってよい文字

変数の名前は自由につけられますが,Python には次のきまりがあります.

  1. 使えるのは英字(a〜z,A〜Z)・数字(0〜9)・アンダースコア _ だけ.空白や - + ! などの記号は使えない.
  2. 先頭に数字は使えない2x はだめ,x2 はよい.
  3. 予約語(Python があらかじめ使っている単語)は使えない.
  4. 大文字と小文字は別の名前lengthLength は違う箱になる.
書き方よい/だめ理由
lengthよい英小文字だけ.読みやすい
right_angleよい_ で単語を区切るのが Python の流儀
x2よい数字は 2 文字目以降なら使える
2xだめ先頭が数字.SyntaxError
right angleだめ空白が入っている.2 つの単語だと思われる
right-angleだめ- は引き算の記号.rightangle と読まれる
classだめ予約語
長さ動くが使わない日本語も通るが,読みにくく打ちにくい.半角英数字で書くこと

表を読むだけでは身につきません.実際にエラーを見ておきましょう. 次のプログラムには,わざとだめな名前が 3 つ書いてあり, どれもコメントアウトしてあります. 1 行ずつ # を外して実行し,どんなエラーになるか確かめてください.

badname.py
# 1 つずつ # を外して実行してみる(外すのは 1 行だけ)

# 2nd_name = "鈴木"      # 先頭が数字
# first name = "太郎"    # 空白が入っている
# from = "広島"          # 予約語

length = 100              # これは正しい名前
print(length)

どれも SyntaxError(文法の誤り)になります. 2nd_nameinvalid decimal literal (数の書き方がおかしい)と言われます.先頭が 2 なので, Python は数を書こうとしていると思って読み始めてしまうのです. 残りの 2 つは invalid syntax です. first name が怒られるのは,Python が firstname という 2 つの単語だと 読んでしまうからです.

3.3.3 予約語

Python が文法のために使っている単語を予約語(キーワード)といいます. これらは変数名に使えません.今は覚えなくてよいですが, 見慣れない色がついたら予約語だと思ってください (右側のコード欄では色が変わります).

Python の予約語(35 語)
False    None     True     and      as       assert   async
await    break    class    continue def      del      elif
else     except   finally  for      from     global   if
import   in       is       lambda   nonlocal not      or
pass     raise    return   try      while    with     yield
命令と同じ名前にしない 予約語ではないけれど,使わないほうがよい名前もあります. print input str int list sum max min など, Python にもともとある命令の名前です. たとえば print = 5 と書いてしまうと,その先 print(…) が 使えなくなります(「5 を呼び出せません」と怒られます). タートルの fd lt rt なども同じです.

3.3.4 意味のある名前をつける

ax でも動きます.しかし 1 週間後の自分は, a が何の数だったか覚えていません. 名前は,読む人へのいちばん短い説明です.

よくない名前よい名前何の数か
alength1 辺の長さ
nside_count角の数
xtotal_price合計金額
bmember人数
troof_angle屋根の角度
Python の名前の流儀 複数の単語をつなぐときは,Python では 小文字とアンダースコアでつなぐのが習わしです (right_angletotal_price). これをスネークケースといいます. 大文字で始めたり,途中に大文字をまぜたりしないでください.

3.4 計算させる

3.4.1 式と演算子

コンピュータはもともと計算機です. length * 2 のように書けば,かけ算をしてくれます. このような計算の書き方を+* の記号を演算子といいます.

演算子意味結果
+足し算7 + 29
-引き算7 - 25
*かけ算(×ではない)7 * 214
/割り算(答えは必ず小数)7 / 23.5
//割り算の(小数以下を切り捨て)7 // 23
%割り算の余り7 % 21
**べき乗(何乗か)7 ** 249
calc.py
a = 17
b = 5

print(a + b)
print(a - b)
print(a * b)
print(a / b)      # 割り算       → 3.4
print(a // b)     # 商           → 3
print(a % b)      # 余り         → 2
print(a ** 2)     # 17 の 2 乗   → 289

3.4.2 /// の違い

ここは必ず引っかかるところです.Python の / は, 割り切れても小数になります

/ と // の違い
print(10 / 2)      # 5.0   ← 5 ではない!
print(10 // 2)     # 5
print(10 / 3)      # 3.3333333333333335
print(10 // 3)     # 3
print(-7 // 2)     # -4    ← 小さいほうへ切り捨てる
整数がほしいときは // タートルの fd は小数を渡しても動きますが, 「個数」「人数」「回数」のように整数でなければ意味がない数を 計算するときは // を使ってください. 「1 人あたり 2142.857142857143 円」では困ります.

3.4.3 余り % の使いどころ

% は「割ったときの余り」を求めます. 地味に見えますが,プログラミングでは非常によく使います.

  • n % 20 なら偶数,1 なら奇数.
  • n % 3012 のどれかになるので,「3 種類の色を順に使う」といった使い方ができる(第 7 章で使います).
  • total % member で,割り勘の「割り切れなかったぶん」が求められる.
mod.py
print(10 % 2)     # 0  → 10 は偶数
print(11 % 2)     # 1  → 11 は奇数
print(14 % 3)     # 2
print(13000 % 7)  # 割り勘のあまり

3.4.4 計算の順番とかっこ

算数と同じで,かけ算・割り算が先,足し算・引き算が後です. べき乗 ** はさらに先に計算されます. 順番を変えたいときは,算数と同じくかっこを使います.

順番演算子
1(先)( ) の中
2**
3* / // %
4(後)+ -
かっこで順番を変える
print(2 + 3 * 4)        # 14   (3 * 4 が先)
print((2 + 3) * 4)      # 20   (かっこが先)
print(100 / 2 * 5)      # 250.0(左から順に)
print(100 / (2 * 5))    # 10.0
ヒント 迷ったらかっこを付けてください. 余分なかっこがあっても遅くなりませんし,エラーにもなりません. 読む人にとっても,書いた人の意図がはっきりして親切です.
虫食い虫食い 3-B 割り算の 3 きょうだい

///% を正しく選んで ____ に入れ,コメントに書いた結果になるようにしてください. 右下の「コンソール」で答え合わせができます.

fill3_div.py
a = 17
b = 5

print(a ____ b)     # 3.4 と出したい
print(a ____ b)     # 3   と出したい
print(a ____ b)     # 2   と出したい

3.4.5 計算させてみる — 月まで何日かかるか

コンピュータに計算させる練習をしましょう. 月まで,時速 80 km の車で行くと何日かかるかを求めます. 月までの距離は約 384400 km です.

手で計算するのは大変ですが,やることは単純です. 距離 ÷ 速さで何時間かかるかが出て, それを 24 で割れば日数になります. 大事なのは,一気に書かずに,途中の結果に名前をつけながら進めることです.

moon.py
distance = 384400     # 月までの距離(km)
speed = 80            # 車の時速(km/h)

hours = distance / speed     # かかる時間(時間)
days = hours / 24            # 日に直す

print(hours)
print(days)

4805.0 時間,200.208… 日と出ます. 休まず走り続けても 200 日.月は遠いのです.

途中の値に名前をつける hours という変数を作らずに days = distance / speed / 24 と 1 行で書くこともできます. 答えは同じです.それでも途中に名前をつけておくと, どこで間違えたかを確かめやすくなりますprint(hours) で途中の値を見れば, 「時間の計算までは合っている」とわかるからです.
数だけ出しても伝わらない このプログラムには,単位が書かれていません4805.0 とだけ出ても,何の数なのか他人には分かりません. 単位や言葉を添えて表示する書き方は 3.7.5 項で扱います. それまでは,せめてコメントに単位を書いておく習慣をつけてください.

3.4.6 計算した結果を変数に入れる

計算した結果も,もちろん変数に入れられます. 次のプログラムは,大きい家と,その半分の大きさの家を並べて描きます. 小さい家の 1 辺は length // 2 で求めています.

double_house.py
from turtle import *

length = 100          # 大きい家の 1 辺
small = length // 2   # 小さい家の 1 辺 = その半分

pensize(2)

# ---- 大きい家 ----
pu()
goto(-150, -60)
pd()

lt(60)
fd(length)
rt(120)
fd(length)
rt(120)
fd(length)

lt(90)
fd(length)
lt(90)
fd(length)
lt(90)
fd(length)
lt(90)
fd(length)

# ---- 小さい家 ----
pu()
goto(50, -60)
lt(180)        # 向きを右向きに戻す
pd()

lt(60)
fd(small)
rt(120)
fd(small)
rt(120)
fd(small)

lt(90)
fd(small)
lt(90)
fd(small)
lt(90)
fd(small)
lt(90)
fd(small)

ht()
done()
図 3.8 length を変えると,2 軒とも同じ比率で大きさが変わる.

length = 100100140 にすると, 小さい家も自動的に 70 になります. 「半分」という関係が,プログラムに書き込まれているからです. 数をじかに書いていたら,こうはなりません.

虫食い虫食い 3-C 入れ子の正方形

大きい正方形の中に,半分の大きさの正方形を描きます. ____ を埋めてください. 小さいほうの 1 辺は 60(整数)になってほしいので, 割り算の記号の選び方に気をつけてください.

fill3_nest.py
from turtle import *

length = 120
small = length ____ 2      # 60 になるようにする

pensize(2)

# 大きい正方形
pencolor("navy")
fd(length)
lt(90)
fd(length)
lt(90)
fd(length)
lt(90)
fd(length)
lt(90)

# 小さい正方形(同じ場所から描き始める)
pencolor("crimson")
fd(____)
lt(90)
fd(____)
lt(90)
fd(____)
lt(90)
fd(____)
lt(90)

done()

3.5 変数の中身を書き換える

箱の中身は入れ替えられます.同じ変数に,何度でも代入してかまいません. 新しく入れると,前の中身は消えます

assign.py
x = 10
print(x)      # 10

x = 25
print(x)      # 25  (10 は消えた)

x = x + 5
print(x)      # 30

x = x * 2
print(x)      # 60

x = x + 5 は,算数として読むと 「x は x より 5 大きい」というありえない式になってしまいます. しかし = は命令でしたから,こう読みます.

  1. 右側 x + 5先に計算する.今 x は 25 なので 30
  2. その 30 を,x の箱に入れ直す
実行した後の x
x = 1010
x = 2525
x = x + 530
x = x * 260
+= という書き方 x = x + 5x += 5 とも書けます. 同じように -= *= /= もあります. 短くて便利ですが,慣れるまでは x = x + 5 と書いて, 右を計算してから左に入れるという流れを意識してください.

= の右側には,変数を書くこともできます. small = big と書くと,big の箱の中身が small の箱に写し取られます. 箱そのものが 1 つになるわけではありません.中身のコピーが渡されるだけです.

copy.py
big = 100
small = big        # big の中身(100)が small に写される

print(big)         # 100
print(small)       # 100

big = 200          # big だけ入れ替える

print(big)         # 200
print(small)       # 100  ← small は 100 のまま
つながっているわけではない 最後の print(small)200 にならないところが大事です. small = big は「これから先 smallbig と同じでいてね」 という約束ではありません.その行を実行した瞬間の値を写しただけです. この後 big をいくら書き換えても,small には伝わりません.

この「入れ直し」を使うと,だんだん大きくなる図形が描けます.

spiral.py
from turtle import *

pensize(2)
pencolor("darkorange")

length = 10

fd(length)
lt(90)
length = length + 12

fd(length)
lt(90)
length = length + 12

fd(length)
lt(90)
length = length + 12

fd(length)
lt(90)
length = length + 12

fd(length)
lt(90)
length = length + 12

fd(length)
lt(90)
length = length + 12

fd(length)
lt(90)
length = length + 12

fd(length)
lt(90)
length = length + 12

fd(length)
lt(90)
length = length + 12

fd(length)
lt(90)

ht()
done()
図 3.9 毎回 length を 12 ずつ増やしながら進むと渦になる.
また面倒になってきた 同じ 3 行が 10 回続いていて,またしても面倒です. 「同じことを繰り返す」書き方は第 6 章で習います. そこでこのプログラムは 4 行になります.

3.6 数と文字はべつもの — 型

ここで用語を 1 つ整理しておきます. プログラムがあつかうデータの一つひとつを値(あたい)といいます. fd(100)100 も, print("こんにちは")"こんにちは" も値です. 箱(変数)に入れるのも,計算するのも,表示するのも,すべて値です.

値には大きく文字があり, 数のデータを数値,文字のデータを文字列(もじれつ)といいます. そして文字列は,必ず "(ダブルクォート)で囲む決まりでした. なぜわざわざ囲まなければならないのでしょうか.

なぜ文字列は囲むのか コンピュータの中では,何もかもが 0 と 1 の並びとして記録されています. 数も文字も,記録された形だけを見れば同じ 0 と 1 の列です. ですから,そのままではどちらのつもりで書いたのかが伝わりません

そこで,「ここからここまでは文字として扱ってください」という印を付けます. それがダブルクォートです. 囲まれていない 100数の 100, 囲まれた "100"「1」「0」「0」という 3 文字です. 見た目は似ていても,コンピュータにとってはまったく別のものです.

Python ではシングルクォート ' で囲んでも同じ働きをしますが, この教材ではダブルクォートに統一します. どちらでもよいところで迷わないためです.

0 から始まる数は書けない 数値を書くときの注意が 1 つあります. 先頭に 0 を付けてはいけませんprint(012345) と書くと SyntaxError: leading zeros in decimal integer literals are not permitted になります.郵便番号や学籍番号のように0 で始まる番号は, そもそも計算するための数ではありません. "012345"文字列にしておくのが正解です.

3.6.1 3 つの型

変数に入れられるのは数だけではありません.文字も入れられます. ただし,コンピュータにとって「7」という数「7」という文字はまったく別のものです. この「データの種類」のことを型(かた)といいます. この教材では当面,次の 3 つを使います.

読み何を表すか書き方の例
intイント整数.小数点のない数7 -3 0 1000000
floatフロート浮動小数点数.小数点のある数3.14 0.5 7.0
strストリング文字列.文字の並び"こんにちは" "7" ""
ここは必ず区別する 77.0"7"3 つとも違うものです. 7 は整数,7.0 は小数,"7" は「7 という文字」です. ダブルクォート " で囲むと,中身がどう見えても文字列になります.

3.6.2 型を調べる — type()

type.py
a = 7
b = 7.0
c = "7"

print(type(a))    # <class 'int'>
print(type(b))    # <class 'float'>
print(type(c))    # <class 'str'>

print(a + a)      # 14      数として足された
print(c + c)      # 77      文字としてつながった!

最後の 2 行に注目してください. 7 + 714 ですが, "7" + "7""77" になります. 文字列に対する +連結(つなげる)を意味するからです.

3.6.3 型は宣言しない

変数を作るときに「これは整数です」と前もって言う必要はありませんlength = 100 と書けば,それだけで整数の変数ができます.

作りたいもの書き方できる型
整数の変数length = 100int
小数の変数rate = 0.05float
文字列の変数name = "かめ"str

Python は,代入された値を見て型を勝手に判断します. これを動的型付けといいます. 書く量が減って楽なのですが,代わりに注意が要ります.

型が途中で変わってしまう例
x = 100        # ここでは int
x = "百"       # ここで str に変わってしまう(Python は文句を言わない)
fd(x)          # ← ここで初めてエラーになる
動的型付けのこわいところ 入れた瞬間には,何も言われません. Python は実行して,その場所まで来て初めてエラーになります. つまりエラーが出る場所と,間違えた場所が離れることがあります. 「1 つの変数には 1 種類のものだけ入れる」と決めておくと,こういう事故が減ります.

3.6.4 小数には誤差がある

float(浮動小数点数)には誤差があります. 次のプログラムは 0.1 を 10 回足すだけですが, 結果は 1.0 になりません.

float1.py
total = 0.0

total = total + 0.1
total = total + 0.1
total = total + 0.1
total = total + 0.1
total = total + 0.1
total = total + 0.1
total = total + 0.1
total = total + 0.1
total = total + 0.1
total = total + 0.1

print(total)      # 1.0 にならない!

0.9999999999999999 と表示されます. ところが 0.125 を 8 回足すと,今度はぴったり 1.0 になります.

float2.py
total = 0.0

total = total + 0.125
total = total + 0.125
total = total + 0.125
total = total + 0.125
total = total + 0.125
total = total + 0.125
total = total + 0.125
total = total + 0.125

print(total)      # こちらはぴったり 1.0
コラム:なぜ 0.1 がずれるのか コンピュータは数を2 進法(0 と 1 だけ)で覚えています. 2 進法では,0.5(=1/2),0.25(=1/4), 0.125(=1/8)のように 「2 で割り切れる小数」はぴったり表せます. ところが 0.1 は,2 進法では 0.000110011001100…無限に続いてしまいます. 10 進法で 1/3 が 0.3333… と書き切れないのと同じことです. 途中で打ち切るしかないので,ごくわずかな誤差が残ります. これは Python の欠陥ではなく, どの言語でも,表計算ソフトでも同じように起きる,2 進法の宿命です.
ヒント ですから,お金のように1 円の狂いも許されない数は, 小数ではなく整数(円単位)で扱うのが定石です.

3.6.5 型を変える — int()float()str()

型を変えたいときは,変えたい型の名前をそのまま命令として使います. これを型変換といいます.

書き方すること
int(x)整数に直す.小数点以下は切り捨てint(3.7)3int("25")25
float(x)小数に直すfloat(3)3.0float("1.5")1.5
str(x)文字列に直すstr(25)"25"
cast.py
print(int(3.7))       # 3    (四捨五入ではなく切り捨て)
print(int(-3.7))      # -3   (0 に近いほうへ切り捨て)
print(float(3))       # 3.0
print(str(25) + "点") # 25点

# 切り捨てを利用した四捨五入
x = 3.7
print(int(x + 0.5))   # 4    0.5 を足してから切り捨てる
切り捨てで四捨五入する int()切り捨てであることを利用すると, int(x + 0.5)四捨五入ができます. Python には round() という命令もありますが, round(0.5)0 になる(偶数側へ丸める)など 学校で習う四捨五入とは少し違う動きをするので,注意してください.

3.6.6 文字と数をまぜて表示する

print("答えは" + 25) と書くとエラーになります. 文字列と数は + でつなげないからです. 方法は 2 つあります.

fstring.py
name = "かめ"
score = 25

# 方法 1:str() で文字列に直してからつなぐ
print("こんにちは," + name + "さん.点数は" + str(score) + "点です.")

# 方法 2:f 文字列(f-string)を使う  ← おすすめ
print(f"こんにちは,{name}さん.点数は{score}点です.")

# 方法 3:print のかっこの中を , で区切る(間に空白が入る)
print("こんにちは,", name, "さん.点数は", score, "点です.")

# f 文字列の中では計算もできる
print(f"来年は{score + 1}点になりますように.")
f 文字列を覚えよう 文字列の前に f を付けるとf 文字列(f-string)になります. その中で { } で囲んだ部分は,変数の中身や計算結果に置き換わりますstr() を書かなくてよいので,短く読みやすく書けます. 今後この教材では,文字と数をまぜるときは f 文字列を使います.
f 文字列の書き方
length = 100
print(f"1 辺は{length}です")          # 1 辺は100です
print(f"半分なら{length // 2}です")   # 半分なら50です
虫食い虫食い 3-D f 文字列で表示する

変数の中身をまぜて 1 行で表示します. ____変数名や式を入れて, ももたろうさんは 18 歳です.来年は 19 歳ですね. と表示されるようにしてください.

fill4_fstring.py
name = "ももたろう"
age = 18

print(f"{____}さんは {____} 歳です.来年は {____} 歳ですね.")

3.7 使う人に入力してもらう

3.7.1 input() で受け取る

ここまでのプログラムは,長さを書いた人が決めていました. input() を使うと,実行する人に決めてもらうことができます. かっこの中に文字列を書くと,それが「何を入れてほしいか」の案内 (プロンプト)として表示されます.

input の基本形
length = input("1 辺の長さを入力してください > ")

input() のところまで来ると,プログラムはそこで止まって入力を待ちます. 右下の「コンソール」の入力行に打ち込んで Enter を押してください. まずは,受け取ったものをそのまま表示してみましょう.

input1.py
text = input("好きな言葉を入力してください > ")

print("あなたが入力したのは")
print(text)
print("ですね")

3.7.2 input() の結果は必ず文字列

input() は数を返さない ここが今回いちばん大事なところです. input() が持ち帰ってくるのは, いつでも,かならず,文字列(str)です. キーボードで 50 と打っても, プログラムが受け取るのは数の 50 ではなく,文字の "50" です.

次のプログラムを開いて実行してみてください.わざと失敗させています.

input2.py
length = input("長さを入力してください > ")

print(type(length))    # <class 'str'>  ← 文字列!
print(length + 10)     # ← ここでエラーになる

TypeError: can only concatenate str (not "int") to str と出ます.「文字列に足せるのは文字列だけです(整数は足せません)」という意味です.

そこで int() で数に直します. int(input(…)) と,かっこが二重になる形を覚えてください.

入力を整数として受け取る定型
length = int(input("1 辺の長さを入力してください > "))
#        ~~~~                                      ~
#        これで文字列を整数に直す
受け取りたいもの書き方
文字列(名前・ことばなど)name = input("名前 > ")
整数(長さ・個数・人数など)n = int(input("個数 > "))
小数(身長・体重・金額など)h = float(input("身長 > "))
input() はいつも文字列 input() は,いつも文字列を返します. 数として使いたいときは,受け取ったあとに自分で int()float() で直すという約束になっています.
数として読めないとき int("あ")int("3.5") はエラー(ValueError)になります. 数として読めない文字が入力されたときの処理は,この教材では扱いません. 入力欄には素直に数を書いてください

3.7.3 入力した大きさの家を描く

input_house.py
from turtle import *

print("家を描きます")
length = int(input("1 辺の長さを入力してください > "))
print(f"1 辺 {length} の家を描きます")

pensize(2)
pencolor("saddlebrown")

# 屋根を描く
lt(60)
fd(length)
rt(120)
fd(length)
rt(120)
fd(length)

# かべを描く
lt(90)
fd(length)
lt(90)
fd(length)
lt(90)
fd(length)
lt(90)
fd(length)

ht()
done()

コンソールの入力行の 12060180 に 書き換えて,もう一度実行してみてください.

図 3.10 60 と入力したとき
図 3.11 180 と入力したとき

3.7.4 2 つ以上の入力を受け取る

input() を 2 回書けば,2 つの値を受け取れます. 2 回とも順番に聞かれるので,1 つずつ打ち込んで Enter を押します.

billsplit.py
print("割り勘計算機")

total = int(input("合計金額を入力してください > "))
member = int(input("人数を入力してください > "))

amount = total // member     # 1 人あたり(切り捨て)
rest = total % member        # 割り切れなかったぶん

print(f"1 人あたり {amount} 円です")
print(f"{rest} 円あまるので,幹事が払ってください")
ヒント // を使っているのは,お金の計算だからです. / にすると 1857.142857142857 円という, 払えない金額が出てきます.
虫食い虫食い 3-E 入力した長さの正三角形

入力された長さで正三角形を描きます. ____ を埋めてください. input() が持ち帰るのは文字列でした. fd() に渡すには何が必要でしょうか.

fill5_input.py
from turtle import *

length = ____(input("1 辺の長さを入力してください > "))

pensize(3)
pencolor("darkgreen")

fd(length)
rt(120)
fd(length)
rt(120)
fd(length)
rt(120)

print(f"1 辺 {____} の正三角形を描きました")

done()

3.7.5 親切なプログラムにする

動くプログラム使えるプログラムは違います. 次は,3.4.5 項の「月まで何日」を入力式に直したものです. 動きますが,使う人にとっては最悪です.開いて実行してみてください.

unkind.py
distance = 384400
speed = int(input())

print(distance / speed / 24)

実行すると,何も言わずに入力待ちで止まります. 何を聞かれているのか分かりません.勇気を出して数を入れても, 今度は 200.20833333333334 とだけ出ます. これが何日なのか,何時間なのか,作った本人しか分かりません.

同じ計算をする,親切なほうを見てください.

kind.py
print("月まで車で何日かかるか計算します")

distance = 384400     # 月までの距離(km)
speed = int(input("車の時速を km/h で入力してください > "))

hours = distance / speed     # かかる時間(時間)
days = hours / 24            # 日に直す

print(f"時速 {speed} km で走ると,月まで {hours} 時間かかります")
print(f"日に直すと,およそ {days} 日です")
print("計算を終わります")

計算しているところは 1 文字も変わっていません. 変えたのは入り口と出口の言葉だけです. それだけで,他人に渡せるプログラムになります.

場面不親切親切
入力を求めるときinput() とだけ書く.画面は黙って止まるinput("車の時速を km/h で入力してください > ")何を・どんな単位で入れるのかを書く
結果を出すときprint(days).数だけがぽつんと出るprint(f"およそ {days} 日です")言葉と単位を添える
始まり・終わり何も出さない.止まっているのか動いているのか分からない「〜を計算します」「終わります」と知らせる
受け取った値何も言わない.打ち間違いに気づけない「時速 80 km で計算します」と読み返す.入力を間違えたことがその場で分かる
誰にとって親切なのか ここでいう「親切」は,見た目を飾ることではありません. 使う人が迷わないようにすることです. そして,いちばん最初に使うのは作った自分です. 親切に作っておくと,自分がデバッグするときにいちばん助かります.
虫食い虫食い 3-F 三角形の面積を求める

底辺と高さを入力してもらい,三角形の面積を求めます. 計算のところはできているので,言葉の部分だけ ____ を埋めて,親切なプログラムにしてください.

ヒント 三角形の面積は底辺 × 高さ ÷ 2 です. 単位(cm)を忘れずに入れてください. 最後の行の { } の中には変数名が入ります.
fill6_triangle_area.py
print("三角形の面積を求めます")

base = int(input("____"))
height = int(input("____"))

area = base * height / 2

print(f"底辺 {base} cm,高さ {height} cm の三角形の面積は {____} 平方 cm です")

3.8 乱数 — 実行するたびに変わる数

乱数(らんすう)とは,でたらめに選ばれる数のことです. これを使うと,実行するたびに結果が変わるプログラムが作れます. Python では random という道具箱を開けて使います.

乱数の基本形
import random                      # 道具箱を開ける(1 行目あたりに書く)

n = random.randint(1, 6)           # 1 以上 6 以下の整数がでたらめに 1 つ
書き方得られるもの
random.randint(1, 6)1 以上 6 以下の整数(さいころ).両端を含む
random.randint(0, 9)0 以上 9 以下の整数(10 種類)
random.random()0.0 以上 1.0 未満の小数
random.choice(["赤", "青", "黄"])並べたものの中から 1 つ(第 16 章で詳しく)
範囲の両端に注意 random.randint(1, 100)1 以上 100 以下random.randrange(100)0 以上 100 未満です. 端をどこまで含むかは命令によって違うので, そのつど確かめる習慣をつけてください.
random_house.py
import random
from turtle import *

length = random.randint(50, 150)     # 50 以上 150 以下
print(f"今回の 1 辺は {length} です")

pensize(2)
pencolor("teal")

# 屋根を描く
lt(60)
fd(length)
rt(120)
fd(length)
rt(120)
fd(length)

# かべを描く
lt(90)
fd(length)
lt(90)
fd(length)
lt(90)
fd(length)
lt(90)
fd(length)

ht()
done()
図 3.12 実行するたびに大きさが変わる家(この図はある 1 回の結果).

何度か実行してみてください.毎回違う大きさの家が描かれます. プログラムは同じなのに,結果が変わるという経験は, 今までになかったはずです.

範囲をずらす random.randint(50, 150) は, random.randint(0, 100) + 50 と書いても同じ範囲になります. 「ほしい範囲にずらす」という発想を覚えておいてください.

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

書き方意味
名前 = 値代入.右を計算して,左の箱に入れる
+ - *足す・引く・かける
/割る.答えは必ず小数10 / 25.0
//割った.小数以下は切り捨て(10 // 33
%割った余り10 % 31
**べき乗(2 ** 101024
int float str整数・小数・文字列の 3 つの型
type(x)x の型を調べる
int(x)整数に直す(小数以下は切り捨て
float(x)小数に直す
str(x)文字列に直す
input("案内 > ")キーボードから 1 行受け取る.結果は必ず文字列
int(input(…))入力を整数として受け取る定型
f"…{x}…"f 文字列.{ } の中が変数の値に置き換わる
import random乱数の道具箱を開ける
random.randint(a, b)a 以上 b 以下の整数を 1 つ

演習

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

作品にするときのきまり 今回からは,先頭のコメントに題名・氏名・日付を必ず書いてください. また,変数には意味のある名前をつけ, 何の数かをコメントで説明することも採点の対象にします.
演習演習 3-1 入力した大きさの正五角形

入力された長さを 1 辺とする正五角形を描くプログラムを与えます. これをもとに,独自のアレンジを加えてください.

  • 大きさの違う正五角形を2 つ以上描く(length // 2 などを使う)
  • 入力された長さから,色や位置も変わるようにする
  • print と f 文字列で,何を描いたかをコンソールにも出す
出発点(100 と入力したとき)
演習演習 3-2 乱数で大きさが変わる星

乱数を使い,実行するたびに大きさが変わる星を描くプログラムを与えます. 乱数は 50 以上 100 以下になるようにしてあります. これをもとに,独自のアレンジを加えてください.

  • 大きさだけでなく,線の太さや位置も乱数で変える
  • 星を 2 つ以上描き,それぞれ別の乱数で大きさを決める
  • pencolor に渡す色は文字列なので,今回はまだ乱数で選べません.かわりに pensize(random.randint(1, 6)) などを試してください
出発点(ある 1 回の結果)
演習演習 3-3 割り勘計算機

合計金額と人数を受け取り,1 人あたりの金額を表示する 割り勘計算機を作ります. 出発点のプログラムは,まだ / を使っていて 「1857.142857142857 円」という払えない金額を出してしまいます.

  1. // を使って,1 円単位の整数で出るようにする.
  2. % を使って,割り切れなかったぶんも表示する.
  3. 幹事だけ多めに払う,端数を切り上げて全員から集める,など独自の分け方を考える.
  4. 余裕があれば:金額を write でタートル画面にも大きく表示してみる.
演習演習 3-4 四捨五入プログラム

実数を受け取り,小数第 2 位を四捨五入して表示する プログラムを作ります. 18.5418.520.1820.2 です.

考え方 int() は切り捨てでした.そこで,
  1. 10 倍する(18.54185.4
  2. 0.5 を足す(185.9
  3. int() で切り捨てる(185
  4. 10 で割る(18.5
という手順で四捨五入ができます. 100 倍・100 で割るようにすれば, 小数第 3 位の四捨五入になります.
  • 小数第 3 位の四捨五入もできるようにする
  • 四捨五入する前と後を,f 文字列で並べて表示する
  • 身長・体重を受け取って BMI を計算し,小数第 2 位で四捨五入して表示する(BMI = 体重kg ÷ 身長m ÷ 身長m)
演習演習 3-5 大きさを自由に変えられる絵

絵全体の大きさを,1 か所の数字で変えられるプログラムを作ります. 出発点は,入力した大きさの家を描くプログラムです.

  1. 家だけでなく,木・太陽・窓・ドアなどを描き足す.
  2. 描き足した部分の長さも,すべて length から計算して決める(length // 2length * 2 など).
  3. length = int(input(…)) の入力値を変えると,絵全体が同じ比率で拡大・縮小することを確かめる.
  4. 余裕があればrandom.randint で大きさを決め,実行するたびに違う風景になるようにする.
数をじかに書かない 「絵全体が同じ比率で変わる」ことがこの演習の目標です. どこか 1 か所でも数をじかに書いてしまうと, そこだけ大きさが変わらずに形が崩れます. じかに書いてよいのは角度だけだと考えてください.
演習演習 3-6 買い物の計算機

ノートと鉛筆を買ったときの合計金額を求めるプログラムを与えます. 値段も個数も,すべて変数に入れてあります. これを,レジのように使える買い物の計算機に育ててください.

  1. 持っているお金を変数 money に入れ,おつりを計算して表示する.
  2. 値段や個数を input() で受け取れるようにして,何を買っても計算できるようにする.
  3. 「〇% 引き」の値段も計算できるようにする.20% 引きなら,もとの値段の (100 - 20) / 100 倍です.割引率も変数にしておくと,10% 引きでも 40% 引きでも使い回せます.
  4. 3.7.5 項を見ながら,親切なプログラムにする.何を入力してほしいのか,出てきた数が何円なのかが分かるようにしてください.
1 円未満をどうするか お金は 1 円単位です.割引の計算は小数になることがあるので, int() で整数に直してから表示してください (int(total * 0.8) のように書きます).
足りなかったら,は次の章 「持っているお金が足りなかったら買えません」と表示したくなったと思います. それには「もし〜なら」という書き方が要ります. 第 5 章で習いますので,今回は足りている前提で作ってください.
演習演習 3-7 あまりの出番

%(余り)と //(商)が主役の演習です. まずは次の問題を,プログラムを動かす前に頭で解いてみてください.

2 つの問題
  1. 友達 7 人とパーティーを開きました.ピザを 6 枚注文し,1 枚は 8 切れに切ってあります.全員が同じ切れ数だけ食べたとき,何切れ余りますか.
  2. 6 本を 1 セットにして売るジュースが 23 本あります.6 本そろったセットから売り場に出します.売り場に出せずに残るのは何本ですか.

出発点のプログラムは,1 の問題を解いているつもりで間違っています. どこが違うかを見つけて直すところから始めてください.

  1. 人数が正しいかを確かめる.パーティーにいるのは誰と誰でしょうか.
  2. 余りだけでなく,// を使って1 人あたり何切れ食べられるかも表示する.
  3. 2 のジュースの問題も同じプログラムの中で解く.何セットできて,何本残るかを両方表示してください.
  4. ジュースの本数と 1 セットの本数を input() で受け取り,数を変えても使えるようにする.
//% はセット // は「いくつ分できるか」,% は「いくつ余るか」です. この 2 つはいつでもセットだと覚えておくと, 「分ける」「詰める」「あまる」という話が出たときにすぐ書けるようになります.
自由演習 3-8 自由制作:変数を使った作品

ここまでに習ったことを使って,自由に作品を作ってください. 前の章と違うのは,変数・計算・入力・乱数が使えることです.

  • 変数を 3 つ以上使い,それぞれに意味のある名前をつけること
  • 計算式+ - * / // % ** のどれか)を使うこと
  • input()random.randint()どちらか(または両方)を使うこと
  • printf 文字列で,コンソールにも何か表示すること
  • 先頭のコメントに題名・氏名・日付を書くこと
題材のヒント 題材に迷ったら:占いプログラム(乱数で数を出して,それを絵の大きさや形に使う), 名前を入力すると文字数ぶんの角をもつ図形を描くプログラム, 年齢を入力すると年齢ぶんの点を打つプログラム, 金額を入力すると硬貨の枚数を //% で計算するプログラム, などはいかがでしょうか.

まとめ

  • プログラムがあつかうデータをという.数のデータが数値,文字のデータが文字列.中身は 0 と 1 で区別がつかないので,文字列は " で囲んで印を付ける.
  • 変数は「名前のついた箱」.数に名前をつけて覚えさせておく.
  • = は等号ではなく代入の命令右を計算してから左の箱に入れる.だから左には箱しか書けない.
  • 名前は英数字と _.先頭に数字は不可,予約語は不可,大文字と小文字は別.意味のある名前をつける.
  • 計算は + - * / // % **/必ず小数//切り捨てた商%余り
  • 型は int(整数)・float(小数)・str(文字列)の 3 つ.Python は宣言しなくても,入れた値で型が決まる
  • float には誤差がある.2 進法で表しきれない小数があるため.
  • int()float()str() で型を変えられる.int()切り捨て
  • input() が持ち帰るのは必ず文字列.数として使うなら int(input(…))
  • 文字と数をまぜて表示するには f 文字列 f"…{x}…"
  • 親切なプログラムにすること.入力を求めるときは何をどんな単位で入れるのかを書き,結果には言葉と単位を添える.数だけ出しても誰にも伝わらない.
  • random.randint(a, b) で,a 以上 b 以下の整数がでたらめに選ばれる.

次の回では,条件によって動きを変える方法を習います. 「入力が 1 なら家,2 なら星を描く」「大吉のときだけ星を描く」といった, 状況を見て判断するプログラムが書けるようになります. 今回おぼえた変数と入力が,そこで一気に生きてきます.