第2版 update: 2021年10月 葛西 真寿 弘前大学大学院理工学研究科
この Notebook は,
テキスト「オープンソースソフトウェアによる情報リテラシー −第2版−」の
のプログラミング部分に相当する内容を,JavaScript のかわりに Python を使い,Jupyter Notebook で書いてみたものです。
エンゲル係数とは,家計の消費支出に占める飲食費(食料費,食費)の割合(パーセント単位)です。
消費支出 110,000円,飲食費 37,000円の人のエンゲル係数を求める例。Python では以下のような電卓的な使い方ですぐ答えが出ます。
本稿のように Jupyter Notebook 環境では,以下の1行を書いたあとに,Shift キーを押しながら Enter キー(または Return キー)を押して実行します。ウインドウ上部のショートカットから「▶︎ Run」をクリックしてもいいです。
37000/110000 * 100
ここからは,単に電卓的に使うだけではなく,応用・発展も見据えて以下のようなプログラム文を作成して実行することにします。
以下の例では,
spending
に消費支出である 110000
(円)という数値を代入し,food
に飲食費である 37000
(円)という数値を代入し,eng
に代入し,eng
を表示させています。# エンゲル係数を求める
# 消費支出 spending, 飲食費 food, エンゲル係数 eng
spending = 110000
food = 37000
eng = food / spending * 100
print(eng)
意に反して,プログラムがうまく動作しない場合があります。たとえば,上記の 3行目を以下のように書いた場合。
掛け算を示す演算子は *
,割り算を示す演算子は /
であるところを誤って,×
や ÷
と書くと,これらの記号は Python では演算子として定義されていないのでエラーとなります。このようなエラーは文法エラー(SyntaxError) と呼ばれ,Jupyter Notebook では,以下のように誤りやその箇所を指摘してくれます。
spending = 110000
food = 37000
eng = food ÷ spending × 100
print(x1)
別の種類の誤りもあります。たとえば,パーセントにするためにかける「100」を誤って「1000」と入力した場合...
spending = 110000
food = 37000
eng = food / spending * 1000
print(eng)
上記の例では SyntaxError
(文法エラー)の警告が出ませんが,答えは明らかに変です。(エンゲル係数の最大値は100だから。)
このような場合はコンピュータにとって誤りではなく,指示通りに計算し,その結果を表示します。 このようなプログラム作成者の不注意や勘違いによって生じるエラーには注意が必要です。
プログラムが正しく動作しない場合は,誤りの箇所を探し,修正して再度動作を確認します。正しく動作するようになるまで,プログラムを修正し,実行(Shift + Enter)します。この作業をデバグといいます。
上記の例の 1行目では,spending
という名前の変数に 110000
という
数値を代入しています。変数名はアルファベットで始まる英数字列にします。大文字と小文字は区別されます。
データ型には数値(整数型・浮動小数点数型)と文字列などがあります。
変数 moji
に文字列を代入する場合は,以下のように "
で囲みます。('
で囲んでもよい。)
moji = "エンゲル係数"
print(moji)
2 + 50 - 5 * 6 /2
2 + (50 - 5 * 6)/2
+
は文字列の連結演算にも使います。以下の例を参照。
mo = "エンゲル"
ji = "係数"
print(mo + ji)
文字列と数値を直接連結することはできません。
そんなときは,str()
関数で数値を文字列に変換して連結します。
spending = 110000
food = 37000
eng = food / spending * 100
output = "エンゲル係数は " + str(eng)
print(output)
print()
のところは,文字列にして連結しなくても,以下のようにも書くことができます。
print()
文は,カンマ (,
) で区切ることによって複数の項目(変数)を表示することができます。
spending = 110000
food = 37000
eng = food / spending * 100
print("エンゲル係数は", eng, "です。")
除算 /
は常に浮動小数点数型の実数を返します。
17 / 3
//
演算子は 整数除算を行い、(小数部を切り捨てた) 整数値を返します。剰余は、%
で求めます。
17 // 3
17 % 3
冪乗は **
です。
以下の例では $2^4 = 2 \times 2 \times 2 \times 2$ と $2^{1/2} = \sqrt{2}$ の値を表示します。
print(2**4)
print(2**(1/2))
1 天文単位(1 au)の距離を光速 c で進むのに要する時間はいくらか。ただし,
149597870700
m299792458
m/s である。参考:
上記の例では,プログラムの中で消費支出や飲食費を決めていましたが,今度はプログラムを実行する人が入力できるようにしてみます。
input()
関数は入力された「文字列」を返すので,数値として計算するために float()
で数値(浮動小数点数)に変換します。
spending = input("消費支出? ")
food = input("飲食費? ")
eng = float(food) * 100 / float(spending)
print("エンゲル係数は", eng)
(これまでの例では1回しか計算していませんが)よく使う計算を「関数」として定義する例です。
以下の例では,1行目から4行目でエンゲル係数を計算する関数 calc()
を定義し,8行目でその関数を呼び出しています。
def calc(spending, food):
""" 消費支出 spending 円と
飲食費 food 円からエンゲル係数を計算する。"""
# 念のため,float() で数値に変換して計算
return float(food) * 100 / float(spending)
spending = input("消費支出? ")
food = input("飲食費? ")
eng = calc(spending, food)
print("エンゲル係数は", eng)
なお,"""
で囲まれた文字列は「ドキュメンテーション文字列(docstring)」と呼ばれる関数の説明文です。
以下のように help()
で参照できます。
help(calc)
いったん定義された関数は,以下のように何回でも利用できます。
calc(120000, 53000)
消費支出を入力すると,エンゲル係数が 20 ~ 40 となる飲食費を表示するプログラムをつくりなさい。
$\sin x, \cos x, \tan x$などの数学関数を使う場合は,以下のように使う前に math
モジュールを import
します。(最初に1回だけ import
すれば,それ以降は一々 import
する必要はありません。)数学定数の円周率 math.pi
なども利用できます。
import math
pi = math.pi;
pi, math.sin(pi/2), math.cos(pi/3), math.tan(pi/4)
以下の例では,x
以下の最大の整数を与える関数 math.floor()
を使って,小数点以下を切り捨てたエンゲル係数の値を表示させています。(ちなみに,小数点以下を切り上げる関数は math.ceil()
です。
また,エンゲル係数を計算する部分はすでに関数 calc()
として定義していますが,プログラム全体を関数 engel()
として定義してしまいます。
def engel():
spending = input("消費支出?")
food = input("飲食費?")
eng = calc(spending, food)
print("エンゲル係数は", math.floor(eng),
"です。(小数点以下切り捨て)")
engel()
Python の組み込み関数に round()
があります。数値を丸める関数ですが,いわゆる四捨五入とはちょっと違うようです。
以下の例からわかるように,小数点以下が 0.5
未満の場合と 0.5
を超える場合は四捨五入と同様の丸め方ですが,ちょうど 0.5
のときは,偶数に丸められていることがわかります。
これを偶数への丸めといい,端数が 0.5
より小さいなら切り捨て,端数が0.5
より大きいなら切り上げ,端数がちょうど 0.5
なら切り捨てと切り上げのうち結果が偶数となる方へ丸めます。
round(12.49), round(12.50), round(12.51)
round(13.49), round(13.50), round(13.51)
条件分岐とは,例えばエンゲル係数の値によって実行文を変えることです。例を示します。
関数 engel()
を以下のように変更します。以下のプログラムでは,エンゲル係数の値が 40 以上だと,「高い値です。」と表示します。
def engel():
spending = input("消費支出? ")
food = input("飲食費? ")
eng = calc(spending, food)
if eng >= 40:
print("エンゲル係数は", math.floor(eng),
"です。高い値です。")
else:
print("エンゲル係数は", math.floor(eng),
"です。")
engel()
engel()
条件分岐の if
文の書式は以下のようになっています。
if 条件式1:
条件式1 が満たされた場合に実行する文
elif 条件式2:
条件式2 が満たされた場合に実行する文
else:
それ以外の場合に実行する文
上の例では,eng >= 40
つまり eng
が 40
以上のとき,という比較演算を行いました。他の例は以下のとおりです。
a == b
a
と b
が等しい
a != b
a
と b
が等しくない
a < b
a
が b
より小さい
a <= b
a
が b
以下
a > b
a
が b
より大きい
a >= b
a
が b
以上
以下の例では,1行目で代入された消費支出に対してエンゲル係数を計算します。
1回だけ計算して表示するのではなく,2行目の飲食費の初期値(ここでは 40000
円)から,5行目の条件式(ここでは 80000
円以下)が成り立つ場合に,8行目にあるように 5000
円ずつ増やしながらエンゲル係数を表示します。
spending = 110000
food = 30000
print("消費支出",spending,"円に対するエンゲル係数の値")
while food <= 50000:
eng = calc(spending, food)
print(" 飲食費", food, "円の場合: ", round(eng))
food = food + 5000
while
文の書式は以下の通りです。
while 条件式:
条件式が成り立つ場合に実行する式
同様の繰り返し処理を for
文を使って行うこともできます。
Python では,以下の例の4行目のように for
文と range()
関数を使って書きます。他のプログラム言語になれていると少しとまどうかも知れませんが,50000
の場合は表示されません。
spending = 110000
print("消費支出",spending,"円に対するエンゲル係数の値")
for food in range(30000, 50000, 5000):
eng = calc(spending, food)
print(" 飲食費", food, "円の場合: ", round(eng))
range()
関数と for
文¶range()
関数を使った for
文の書式は以下の通りです。開始値を省略すると 0
とみなし,増分を省略すると 1
とみなします。
for i in range(開始値, 終端値, 増分):
i が開始値以上,終端値未満の場合に実行される文
以下の range(5)
とした例を参照してください。
for i in range(5):
print(i)
以下の値を求めるプログラムを作成せよ。
$$\sum_{n = 1}^{10} n^2$$# リスト a の要素の値を設定
a = [5, 4, 3, 2, 1]
print("全成分を一挙に表示")
print(a)
このようにして作られるのがリストであり,type()
関数で確認できます。
type(a)
少し表示を工夫してみます。
print("全成分を横に表示")
[print(i, end=' ') for i in a];
print("")
print("全成分を縦に表示")
[print(i) for i in a];
5個の成分を全てゼロにしてリストを初期化する例です。
# リスト b の5つの要素を全て 0 に
b = [0] * 5
print(b)
# 3番目の要素の値を設定
b[2] = 3
print(b)
以下のようなテキストファイル mydata.txt
を用意します。
! cat mydata.txt
ファイル mydata.txt
の数値をリスト a
に読み込みます。まずは readlines()
を使って読み込んでみます。
f = open("mydata.txt")
a = f.readlines()
print(a)
type(a)
import numpy as np
a = np.loadtxt('mydata.txt')
print(a)
import numpy as np
としてインポートした後,np.loadtxt()
関数で読み込むと,a
は numpy.ndarray
という配列になります。
type(a)
np.loadtxt()
はデフォルトでは実数として読み込みます。整数として読み込む場合は,以下のように dtype='int'
オプションを設定します。
a = np.loadtxt('mydata.txt', dtype='int')
print(a)
# 要素の総和,平均,最大値,最小値を出力します。
print("要素の総和は", sum(a))
print("要素の平均は", sum(a)/len(a))
print("最大値は ", max(a))
print("最小値は ", min(a))
次は,以下のような「6行2列」のデータが入ったテキストファイル mydata2.txt
を読み込む例です。
! cat mydata2.txt
b = np.loadtxt('mydata2.txt', dtype='int')
print(b)
np.savetxt()
による書き込み¶ファイルへの書き込み例です。この例では,$x$ と $\sin x$ の値を $x = 0.1$ から $x = 1.0$ まで書き込んでいます。
import numpy as np # 1度 import していればいいですが,念のため
# まず,書き込む配列を作成します。
x = []
for i in range(1, 11):
xi = 0.1 * i
x.append([xi, np.sin(xi)])
# 配列 x をファイル myoutput.txt に書き込みます。
np.savetxt('myoutput.txt', x)
# myoutput.txt の内容を表示します。
! cat myoutput.txt
np.loadtxt()
で読み込むと,numpy.ndarray
という配列になります。
type(b)
配列の成分の参照は以下のとおりです。例えば,3行2列目の値を参照したいときは,Python はゼロ始まりですから...
b[2,1]
tolist()
¶配列 numpy.ndarray
から Python 標準のリストに変換する場合は以下のように tolist()
を使います。
blist = b.tolist()
print(blist)
リストの場合の成分の参照例:
blist[2][1]
numpy.array()
¶Python 標準のリスト list
から配列 numpy.ndarray
へ変換する場合は,以下のようにnp.array()
関数を使います。
上記の方法で作成した x
は Python 標準のリストです。
type(x)
xarray = np.array(x)
type(xarray)
ndarray
のほうが,print()
したときに整って表示されます。
print("成分の参照の仕方:")
print("x[9][1] = ", x[9][1])
print("xarray[9,1] = ", xarray[9,1])
print()
print("list")
print(x)
print()
print("ndarray")
print(xarray)
import numpy as np # 最初に1回やればいいが,念のため
ten = '1234567890'
print(ten * 2, "桁数")
sqrtwo = np.sqrt(2)
print(sqrtwo) # NumPy の sqrt は全18桁
print('%8.5f' % sqrtwo)
print('%18.15f' % sqrtwo)
print('2の平方根は %18.15f です。' % sqrtwo)
小数点以下のみの桁数を指定することもできます。例えば,'%.5f'
のように小数点以下5桁のみを指定します。
print(ten * 2, "桁数")
print('%.5f' % sqrtwo)
print('%.15f' % sqrtwo)
以下の出力を,エンゲル係数の値を(四捨五入して)小数点以下1桁まで表示するように変更しなさい。
spending = 110000
food = 37000
eng = food / spending * 100
print("エンゲル係数は", eng, "です。")
非常に大きい数や小さい数を表示するときには, $1.9891\times 10^{30}$ や $6.67430\times 10^{-11}$ などのような指数表示をします。
例えば '%e9.2'
では,全体で 9
桁の表示分を確保し,小数点以下は 2
桁表示します。
print(ten * 2, "桁数")
c = 299792458
print('%9.2e' % c)
print('%15.8e' % c)
print('光速は %15.8e m/s です。' % c)
小数点以下のみの桁数を指定することもできます。例えば,'%.2e'
のように小数点以下2桁のみを指定します。
print(ten * 2, "桁数")
print('%.2e' % c)
print('%.8e' % c)
print('光速は %.8e m/s です。' % c)
ten = '1234567890'
print('%s 桁数' %(ten*2))
print(ten[:5]*2)
print(ten[:6]+ten[:4])
整数の書式指定は '%d'
です。'%5d'
のように桁数を指定することもできます。
v = [1, 23, 456, 7890]
for row in v:
print(row)
# 書式指定で表示桁数を5桁とり,右寄せで整数を表示
for row in v:
print('%5d' % row)
m = [[1, 0, 0, 0],
[0, 23, 0, 0],
[0, 0, 456, 0],
[0, 0, 0, 7890]]
for row in m:
for col in row:
print(col, end=" ") # 改行せずにスペース1個あけて出力
print() # 改行
# 書式指定で表示桁数を5桁とり,右寄せで整数を表示
for row in m:
for col in row:
print('%5d' % col, end=" ")
print()
この Notebook では,プログラミング言語として共通の部分に焦点を絞った Python の使い方について解説しました。
さらに発展的な Python の活用例については,以下のページを参考にしてください。
また,本家サイトのドキュメントは以下から。