1. Pythonの基本 その1:#
授業の冒頭で説明するように、プログラミングによるデータ分析は、複雑なデータの取り扱いを簡単にしてくれたり、系統的な作業を可能にしミスを減らし、計算の精度を確かめることが出来たりと利点が多い。しかし、その恩恵を受けるためには基本的な事項をまず学修しなくてはならない。
この授業で重視するのはPythonの文法や作法、テクニックではない。というのも、自分が実現したい操作・作業をきちんと言語化することさえできれば、授業で扱う程度の内容であればググればだいたいのことは解決できるし、インターフェース(見た目)が違ったとしても別のプログラミング言語やデータ解析ツールにも応用が効く。
したがって、以降では「いったいなんのためにホニャララなんてものを導入(定義)するのか?」を意識しながら学習していくことにしよう。
1.1. 変数の定義と簡単な演算#
Pythonでは、値に名前を付け、その名前を使って値を参照する。この名前を変数と呼ぶ。
どのようなものが「値」として扱えるかは後で見ていくことにして、まずは小数点を含む数と整数を変数に代入してみよう。
a = 2.0
b = 5
print(a)
2.0
これで変数 a と変数 b に値が代入され、定義された。
Pythonでは、等号記号 = は代入に使用される。左に変数名、右に代入する値や式を書く。
注: 変数を「値を入れる箱」に見立てる説明もよく見られるが、Pythonでは「値を指す名前」と考えると分かりやすい。複数の名前が同じものを指すこともある。関連した話題は、次の章のリスト操作の注意点を参照。
1.2. 簡単な演算#
次に、上で定義された変数を使って四則演算をしてみよう。
足し算
a + b
7.0
引き算
a - b
-3.0
掛け算 掛け算記号は*(アスタリスク)
a * b
10.0
割り算
a / b
0.4
演算した結果を別の変数cとして定義したり代入して保存しておくこともできる
c = a * b
cの値が後で知りたいと思ったときは、以下のようにprint関数というものを使う
print(c)
10.0
変数の値を確認することは、プログラムが正しく動いているかを確認する最も単純かつ強力な方法である。
慣れないうちは「値はなんだっけな?」「何かおかしい、意図した動きと違うな」と思ったらprintしてみよう。
また、文字列の外でコード部分に#(半角シャープ記号)をつけるとその行の#以降に書かれたことは無視されるのでコメント(注釈)を書いたりすることができる。
print("Hello") # Helloとプリントする(ここは読まれない)
Hello
慣れないうちはどういった計算をするのか、その行をいつ編集したのかなどコメントを逐一書いておくのも良い。
# 10月1日に編集
print(b // a) # 切り捨て除算(負の無限大の方向に丸める)
print(b % a) # bをaで割った余り
print(a**b) # aのb乗
2.0
1.0
32.0
上の例で、#を忘れると
print("Hello") Helloとプリントする
Cell In[11], line 1
print("Hello") Helloとプリントする
^
SyntaxError: invalid syntax
構文エラー(SyntaxError)が発生する。
基本的にSyntaxError:はあなたの書いたコードがPythonの文法上許されない書き方になっていることを意味している。
print("Hello")
Cell In[12], line 1
print("Hello")
^
SyntaxError: invalid character ')' (U+FF09)
は一見問題ないように見えるが、print関数の右側の括弧)が全角になっているため、これもSyntaxErrorとなる。
細かな文法やエラーの原因の特定については、一緒に少しずつ慣れていこう。
一度定義した変数は、値を更新することもできる。ここでは数値の場合を考えよう。
a = a + 2は、"aに2を加えた値"でaを再定義することを表し、a += 2と書いても同じ結果が得られる。(+= を用いた書き方のほうがシンプルなので、今後多用します)
a = 2.0
a += 4.0
print("2つ目の操作 += 4.0 =>", a)
a -= 3.0
print("3つ目の操作 -= 3.0 =>", a)
a *= 3.0
print("4つ目の操作 *= 3.0 =>", a)
a /= 3.0
print("5つ目の操作 /= 3.0 =>", a)
2つ目の操作 += 4.0 => 6.0
3つ目の操作 -= 3.0 => 3.0
4つ目の操作 *= 3.0 => 9.0
5つ目の操作 /= 3.0 => 3.0
+= のほかにも、引き算・掛け算・割り算に対応する -=、*=、/= が使える。
1.3. 変数名に関する約束#
この授業では変数名に全角文字(ひらがな・カタカナ・漢字)は使わず、文字列かコメントにのみ使うと約束をしよう。
# 非推奨
あ = 1.0
print(あ)
1.0
Pythonでは変数名にひらがなや漢字を使うこともできる。この授業では、コードを読み書きしやすくするために半角英数字とアンダースコアを使う。
また、変数名などにひらがなを使うことに由来して起こりがちなバグとしては「括弧()を間違って全角にしてしまってそれに気が付かない」といったことがある。コードを編集する際に日本語の変数などを利用していると、半角・全角の切り替え忘れなどが生じうるので、コードセルではなるべく半角英数字のみを使うというのが、ミスを防ぐための一つの方法にもなっている。
以降ではこの慣例にならって、変数名に全角文字は使わない。変数名は基本的に半角英数字, アンダースコア_のみで定義しよう。
+-%/=などの記号も使うことができない。たとえば-は既に引き算という演算を表すのに使用されているので、a-b という名前の変数を定義しようとしても、コンピュータにとっては変数ではなく[a マイナス b]という演算だと認識されてしまう。
また変数の頭に数字を使うこともできない。 例: 2a
a = 5.0
a2 = a * 2.0 # これはOK
# 2a = a * 2.0 # これは構文エラー(SyntaxError)
その他、よくあるエラーについてはこちらを参照
1.4. Pythonでの文字列操作#
Pythonでは、数値はもちろん文字列も値として扱うことができる。文字列は""(ダブルクォーテーション)か''(シングルクォーテーション)で囲むことで定義することができる。
text = "私の名前はXXXです" # XXXのところを自分の名前にしてみましょう。
print(text)
私の名前はXXXです
文字列には、足し算や整数値との掛け算が適用できる。たとえば
text1 = "ティッシュ配りの"
text2 = "バイトを監視する"
print(text1 + text2)
ティッシュ配りのバイトを監視する
とすれば、text1とtext2にそれぞれ代入した2つの文字列を連結した一つの文字列を表示することができる。
また、
a = 2
print(str(a) + "人の" + text1 + text2 * 5 + "正社員")
2人のティッシュ配りのバイトを監視するバイトを監視するバイトを監視するバイトを監視するバイトを監視する正社員
とすれば、text2部分を5回繰り返して他の文字列とつなぎ合わせた長い文字列を作ることもできる。
1点注意点としては、整数値を代入したaを文字列として他の文字列と結合したいときは、
str()関数(strはstringの略)を使って、文字列に変換してやらなくてはならない。
これに関連して、後ほど変数の型というものを勉強する。
また足し算と掛け算は定義できるが、文字列に対して引き算や割り算を行おうとするとエラーを吐く。
※もう少し詳細な文字列操作
replace関数,split関数,strip関数なども便利だが、この章では省略する。以降の"ファイル・文字列操作"の章で扱う。
1.5. プログラムの実行順#
基本的にプログラミングでは、上から処理が実行される。
(ループや関数が導入されると少し事情が異なり、ブロックと呼ばれる処理単位でまとめて実行されることもあるが、この点については、2・3章以降で追々見ていく)
以下の2行のコードは、実行するとエラーが出る。
print(num)
num = 2
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
Cell In[20], line 1
----> 1 print(num)
2 num = 2
NameError: name 'num' is not defined
理由は、エラーメッセージを読むと分かるように、num という変数が定義されていない(not defined/undefined)のに、その値を print しようとしたからである。
もちろん、先に num = 2 を実行していればエラーは出ない。ノートブックでエラーにならなかった場合は、以前の実行で num が定義されていないか確認しよう。
num = 2
print(num)
2
とくにGoogle Colab(Jupyter Notebook)環境では、セルをまたいでコードを実行することがあるので、意図した変数の値がきちんと引き継がれているか注意が必要になる。また変数のスコープという概念にも注意が必要となる(関数を扱う第3章で解説).
実行順が分からなくなったら、ランタイム(カーネル)を再起動して上から実行し直すと、以前の変数が残っているせいなのかを切り分けられる。
Jupyter Notebook環境では、セルのコードを逐次実行した場合コードセルの左側に表示される括弧[ ]内の整数でコードの実行順を確認することができる。コードやノートが複雑になってくると、正しい順番で実行しないとエラーが出たり、エラーは出ないけれど意図した出力にならないといった事が起こりえるので、注意が必要。慣れないうちは、処理(プログラム)をあまりバラバラのセルに書かず、一つにまとめて書くのがオススメ
一つのセルにまとめる例
a = 2
f = a**2 + 3 * a + 1
print(f)
11
セルを分ける例(実行順に注意)
a = 5
f = a**2 + 3 * a + 1
print(f)
41
このようにコードを分けてしまうと、fでは最後にaに代入された値を用いて計算が行われるので、a=5のセルを実行し忘れると、意図した値にならない。(あるいは未定義ならエラーとなる)
1.6. 変数の型#
プログラムの中で扱う値には様々な"型"(type, タイプ)が存在する。
代表的なものとしては、
float: 浮動小数点数(≒実数の有限桁内の近似)int: 整数str: 文字列 (stringの略)bool: 真偽値 (下で説明します)
が挙げられ、この他にも様々な型が存在している。
たとえば以下のように変数の型はtype()という関数を使うことで調べることができる。
a = 2
b = 2.0
print(type(a), type(b))
<class 'int'> <class 'float'>
a=2はint(整数)型で、b(=2.0)はfloat、つまり浮動小数点(floating point)。
Pythonでは特定の型同士のみに許された特殊な演算等もある。変数の型が調べたくなったときはtype関数を使ってみよう。
1.6.1. プログラムでの実数の取り扱い#
int 型の 2 と float 型の 2.0 は、どちらも整数の2を正確に表せる。ただし、float であらゆる実数を正確に表せるわけではない。
たとえば、以下の長い小数を変数 a に代入して print してみよう。
a = 2.00000000000000000000055511151231257827021181583404541015625
print(a)
2.0
入力した値が、float で表せる近い値に丸められ、2.0 になった。
Pythonの float は通常、IEEE 754の倍精度形式を使い、十進数でおよそ15〜16桁の有効数字を扱える。ただし内部では二進数なので、十進数では短い 0.1 も正確には表せない。
たとえば、数学では 0.3 と 0.1 + 0.1 + 0.1 は等しいが、コンピュータではそれぞれの値や演算結果が丸められるため、差を取ると……
print(0.3 - (0.1 + 0.1 + 0.1))
-5.551115123125783e-17
というように、ごく小さな値だけずれていることが分かる。
普段の計算では気にならないことも多いが、== での比較や、誤差が積み重なる計算では影響が出る。研究などで数値計算を行う場合には、こうした誤差を見積もり、必要な精度が得られているか確かめることも大切になる。
詳しくはPython公式ドキュメント: 浮動小数点数の演算を参照。
\(\clubsuit\) さらに進んだ注
コンピューターでは、0か1の二値を取るビット(bit)を最小単位として数値など各種の情報を表現して扱う。 たとえば整数値は、ビットを用いた表現と1対1対応させることができる。ビットが2つ使えるとするならば、[00]が0, [01]が1,[10]が2,[11]が3といった具合(あくまで割当の一例にすぎないが、これは二進表現そのものである)。
使うビット数が有限なら、表せる値の種類も有限である。そのため、あらゆる実数をそのまま表すことはできず、多くの値には近似が必要になる。広い範囲の数を限られたビット数で表す方法が浮動小数点であり、その標準を定めたものがIEEE 754である。
1.7. 予約語#
Pythonには、あらかじめ文法上の役割が与えられた言葉(予約語)があり、変数名として使うことはできない。
使用中のPythonの予約語は、以下で一覧を確認できる。エディタでは色が変わることもあるが、色分けだけで判断しないようにしよう。
import keyword
print(keyword.kwlist)
['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']
1.8. ブール(bool)#
真偽値(bool,ブール)はTrue(真)とFalse(偽)の二値を取る型である。たとえば
a = 2.0
b = 5.0
のとき、
print(a < b) # aがbより小さいかどうか
True
print(a == b) # aがbと等しいかどうか プログラムでの等号は=ではなく==です。
False
これを考えるとなにが嬉しいかというと、ある条件をみたす(みたさない)ときだけ特定の作業をするプログラムを書くことが出来る。
if a == b:
print("aとbが一緒だよ!!やったね!!!")
else:
print("aとbが違うじゃないか!!!!")
aとbが違うじゃないか!!!!
このような条件分岐の書き方については、次の章で見ていくことにしよう。
1.9. \(\clubsuit\) 参考: フォーマット文字列#
Pythonでは、文字列の中に変数の値を埋め込み、多彩な表示を行うことができる。 例えば特定の数値を桁数を指定したり、右・左寄せで表示したり、指数表記にしたりといったことが可能である。
イメージとして、ゲームを作成している際のメッセージ表示を考えてみよう。 HPやMPの値を表示する際に、桁数を揃えたり、右寄せで表示したりすると見た目が整い、プレイヤーにとって分かりやすくなる。 数値の変化に伴ってスラッシュなどの位置が変わると見にくいので、スラッシュの位置を固定して表示したいといったこともあるだろう。
Pythonでは、以下の f文字列(フォーマット済み文字列) を使うと、変数の値を文字列に埋め込むことができる。文字列の前に f を付け、埋め込みたい値や式を {} で囲む。
a = 1 / 3
b = 5
c = "やぁ、ここはXX村だよ"
d = "こんにちは!"
print(f"小数点以下6桁まで表示すると...{a:.6f} 指数表示すると...{a:.1e}")
print(f"HP:{b:>3d}/999") # 右寄せで3桁表示
print(f"HP:{10*b:>3d}/999") # 右寄せで3桁表示
print(f"村人「{c:s}」")
print(
f"1/6について、{b}桁まで表示するよ => {1/6:>.{b}f}"
) # 変数をformat文字列の中で使うこともできる
小数点以下6桁まで表示すると...0.333333 指数表示すると...3.3e-01
HP: 5/999
HP: 50/999
村人「やぁ、ここはXX村だよ」
1/6について、5桁まで表示するよ => 0.16667
ちなみに、古くからある % を使った書式指定も、この資料では用いている:
print("%.3f" % (1 / 3))
0.333