Python演習1

実験の目的

科学技術計算で用いられるプログラミング言語であるPythonの基礎的な使い方を理解する。

ドキュメントについて

このドキュメントは、みなさんが実際に手を動かしながらPythonというプログラミング言語を学ぶためのものです。

プログラミングは一朝一夕では身につかないので、繰り返し練習してみてください。

Pythonとは?

プログラミング言語のひとつです。1991年と、比較的新しく開発された言語(C言語は1972年)です。理解しやすく書きやすく、パフォーマンスの良い書き方もできるなど、現代的な言語に求められる特性を多く備えており、科学技術計算のほか、Webや機械学習など、幅広い用途で使われています。

現在はPython 3系 が主流となっています。以前のPython 2系とは若干書き方が異なるため、書籍などを参考にする際にはバージョンを確認する必要があります。

C言語とは違うの?

違います。たとえば、[2, 4, 1, 5, 3]という数字の並びを小さい順に並び替えるプログラムを見てみます。

Cでの例は以下のようなものです(バブルソートという方法を使っています)。

#include <stdio.h>
int main(void)
{
    int i, j;
    int num[5] = {2, 4, 1, 5, 3};
    int tmp;
    for (i = 0; i < 5; i++)
    {
        for (j = i + 1; j < 5; j++)
        {
            if (num[i] > num[j])
            {
                tmp = num[i];
                num[i] = num[j];
                num[j] = tmp;
            }
        }
    }
    for (i=0 ; i < 5 ; i++)
    {
        printf("%d ", num[i]);
    }
    return 0;
}

対してPythonでは以下のようになります。

num = [2, 4, 1, 5, 3]
for i in range(len(num)):
    for j in range(i + 1, len(num)):
        if num[i] > num[j]:
            num[i], num[j] = num[j], num[i]
print(num)

明らかに記述の量が違いますね。Pythonのほうが見やすいし、プログラムも短いです。

C言語は余計な命令を書いているのでしょうか?いいえ。すべて必要な命令です。では、なぜこの違いが?

Pythonは、可読性(読みやすさ)や書きやすさに重点が置かれた言語です。難しい処理も簡潔に記述することを得意としています。

しかし、万能な言語ではありません。

たとえば、Pythonのプログラムにintが出現していないことに気付いたでしょうか。C言語では、変数を宣言するときは、必ずその変数に入るのが整数なのか、浮動小数点なのか、はたまた文字なのかを指定しなければいけません。

しかし、Pythonはそれを自動で行います。変数に値が代入されるときに、それが数字なのか、文字なのかを判断して、適切なを推論します。

これは一見嬉しいことのように思いますが、プログラムのバグを増やす要因になります。数字だと思って処理を書いたのに、実は文字列が入っていた、となると、プログラムは誤った動作をします。Pythonはこういったバグを生み出しやすいのです(もちろん、これを防ぐ方法もあります)。

Pythonの書きやすさには、文法の工夫に加えて、こうした「よしなにやってくれる仕組み」が貢献しています。この仕組は趣味の工作でPythonを使うには気が利いて便利ですが、たとえば銀行の勘定系システムを作るときには役に立ちません。

あいまいさを許容する言語は、書いたプログラムがCPU上でどのように実行されるのか?私たちにとってわかりにくくなります。厳密なプログラミングを行いたい場合、C言語のようにあいまいさが排除された言語を使った使ったほうがよいのです。

世の中には数百、数千、あるいはそれ以上のプログラミング言語がありますが、それぞれが利点と欠点を持っています。そのため、プログラマーはいくつもの言語を習得して、用途に応じて使い分けています。

Pythonはどのようなときに使いやすい?

では、Pythonにはどのような利点があるのでしょうか?

文法が書きやすく、読みやすい

上の例のように、Pythonでは余計なカッコなどで混乱することが少なく、人間にとって理解しやすく書けます。

オブジェクト指向言語

これはずっと後で説明しますが、現代的で人間が理解しやすいプログラミングの考え方を使えます。

世界中の多くの人が使っている

多くの人が使うため、言語を理解するための資料がたくさんあります。また、科学技術の計算などをさらに便利にするためのプログラム(ライブラリ)がオープンソースとして配布されており、自由に使うことができます。上で示した数字の並べ替えも、ライブラリを使うともっと簡単なプログラムで実現できます。

Python実行環境の設定: Google Colab

皆さんの使っているWindows PCでPythonを使うためには、Pythonが動作する環境を設定する必要があります。

Note

Windows PCでは、AnacondaWSL2を使ってPythonの実行環境を設定できます。MacOSやLinuxディストリビューションの多くは標準でPythonが入っています。

これは少し技術的に難しいので、今回はGoogleのサーバーを使ってブラウザ上でPythonが実行できる Google Colaboratoryを使って演習を行います。

まずはGoogleアカウントを作成し、colab.research.google.comにアクセスしてください。

以下のような画面が出てくるので、ノートブックを新規作成をクリックします。

以下のようにプログラムの入力欄が出てきます。試しに、文章を表示するかんたんなプログラムを入力してみます。

灰色の四角をセルといいます。セルの中にプログラムを入力します。

print("Hello world!")

そして、左にある実行ボタン▶を押してしばらく待つと…

プログラムが実行され、Hello world!という文が出力されました!

課題

print("好きな言葉")で、好きな言葉を表示してみましょう。好きな言葉の前後に"(ダブルクォート)を必ず入れてください。
この課題ができたら、、先生に確認してもらってください。次からの課題は、特に指示がなければ先生に見せずに進んでも良いです。

Tip

Google Colabでは、プログラムと実行結果を同じファイルで見ることができるJupyter notebookというファイル形式を使っています。ファイルはGoogleドライブに自動で保存されているので、保存されていればブラウザを閉じても後でプログラムと実行結果を確認できます。

変数

C言語と同様、Pythonにも変数があります。変数はなにか値を入れるための箱といえます。まずは使ってみましょう。下のプログラムを入力してください。

a = 1
print(a)

1が出力されましたか?変数aに値1代入されたため、変数aを表示(print)すると1が出力されます。

もうひとつやってみましょう。

b = 5
print(b)

次は、これらの変数を使って計算をします。

c = a * b
print(c)

*はかけ算を表しています。正しい結果が表示されたでしょうか。

他にも以下のような演算子が使えます。

演算子 意味
+ 足し算
- 引き算
* かけ算
/ わり算
// わり算の商
% わり算の余り
** べき乗
d = 3 + c * b
print(d)

意図した結果が出力されたでしょうか?

課題

答えが"42"になる数式を作り、printしましょう。

ここまで整数のみの計算をしましたが、変数には小数点のある数や文字列など、いろいろな値を格納することができます。

e = 3.14
print(e)
f = "hello"
print(f)

文字列を入力するときは、""で囲うことを忘れないでください。変数と文字列を区別するしるしです。

変数は何でも入って便利ですが、実は、コンピュータの内部では、それぞれの変数が整数を入れるための箱か、小数か、あるいは文字列を入れるための箱なのかを区別して記憶しています。これをといいます。

C言語では型を厳密に守らないとエラーが出ますが、Pythonでは自動的に型を推論してくれるため、いつも気にしなければいけないわけではありません。

では、それぞれの変数がどんな値を入れるための箱なのか?type(変数などのオブジェクト)で確認できます。下のプログラムは、type(変数などのオブジェクト)をprintで表示しています。

a = 1
print(type(a))
e = 3.14
print(type(e))
f = "hello"
print(type(f))

いろいろな型があります。type()に値を直接入れても結果が出ます。

print(type(3))

Tip

intはintegarつまり整数、floatはfloating numberつまり浮動小数点数、strはstringつまり文字列を意味します。浮動小数点数とは、ある程度の有効数字でとても大きな数やとても小さな数を表せる仕組みを使った数です。

課題

3.14"3.14"の型(type)を確認してみましょう。

いま使っている変数の型が何なのかを理解しながらプログラムを組まないと、型の違いによって処理が異なっておかしなことになる場合があります。

課題

3.14 + 3.14と、"3.14" + "3.14"をそれぞれprintして比べてみましょう。

エラー

以下のプログラムを実行しようとすると、

f = "hello"
print(f * 3.14)

結果の代わりに、なにやら英文が表示されました。

TypeError Traceback (most recent call last)
<ipython-input-...> in <cell line: 2>()
      1 f = "hello"
----> 2 print(f * 3.14)

TypeError: can't multiply sequence by non-int of type 'float'

これはエラーです。Pythonがうまくプログラムを実行できないときに発生します。この場合、"hello"という文字列に3.14をかけることはできないため、和訳すると「この型(文字列)は浮動小数点数でかけることができません」と表示されています。

エラーのとき表示されるエラー文は、プログラムのどこでどのようにうまく動かなかったかを説明しています。プログラムを修正するときにはまず、エラー文が何を言っているのか理解する必要があります。

とはいえ、最初は難しいので、エラーが出たら先生に見てもらうと良いでしょう。

空白

ここまでのプログラムには、たくさんの半角スペースが入っていました。

たとえば、

e = 3.14
print(type(e))

これは、実はスペースがなくても動きます。

e=3.14
print(type(e))

逆にいっぱい入れても良いです。

e      =      3.14
print( type( e ) )

ただし、意味のあるまとまりの途中で半角スペースを入れるとエラーになります。

e = 3.14
pri nt(typ e(e))

このプログラムはエラーになります。

  File "<stdin>", line 1
    pri nt(typ e(e))
         ^
SyntaxError: invalid syntax

何のために半角スペースを入れるかと言うと、見やすさのためです。この演習を通じて、見やすい半角スペースの入れ方を考えてみてください。

Warning

全角スペースは絶対に使わないでください。エラーになります。

配列

Pythonで配列のような型はいくつかありますが、ここではリストを学習します。

リストとは、下のようにコンマで区切っていくつかの要素を入れることができる型です。リストは[]で囲みます。

g = [10, 20, 30, 40, 50]

リストの中のそれぞれの要素には要素番号が以下のようについています。0から始まることに注意してください。

要素番号を指定することで、要素を取り出すことができます。

print(g[2])

課題

リストgから、要素番号4の要素を取り出してみましょう。

ある範囲の要素をまとめて取り出すこともできます。たとえば

print(g[1:3])

[20, 30]となり、要素番号1から3の1つ前までの要素を取り出せました。

課題

リストgから、リストの2番めから4番目までの要素を抜き出してみましょう。

リストのリストを作ることもできます。

h = [[10, 20],
     [30, 40]]

ライブラリ

これまでprint()type()などの命令を使いました。このように文字の後ろにかっこ()がついていて、かっこの中身に処理するデータを入れる命令を関数といいます。

print()type()はPythonにあらかじめ用意されている組み込み関数です。

課題

数値の絶対値を求める組み込み関数はabs()です。かっこの中に数字を入れて動作を確認しましょう。

Tip

Pythonの組み込み関数一覧は、下のサイトでチェックできます。 https://docs.python.org/ja/3/library/functions.html

科学技術の計算をするときには、組み込み関数だけでなく、もっといろいろな関数を使いたい場合があります。例えば、sinやcosを計算できたら便利です。

そういったときに、色々な機能をまとめたライブラリを活用できます。まずは、標準ライブラリのmathを使ってみましょう。

ライブラリを使うときは、インポートを行います。

import math

これでmathライブラリが使えるようになりました。試しにsqrt()関数を使ってみましょう。引数の平方根をとる関数です。

import math

k = math.sqrt(2.0)
print(k)

インポートしたライブラリの関数を使うには、頭にmath.をつけます。

課題

mathライブラリの関数fabs()は、引数の絶対値を返す関数です。-2の絶対値をとってみましょう。

次に、行列計算を高速に行えるNumPyというライブラリをインポートしましょう。Pythonでは、ライブラリに別名をつけることができます。

import numpy as np

これでNumPyにnpという別名をつけてインポートしました。同様に、グラフ描画のためのmatplotlibというライブラリをインポートします。

import matplotlib.pyplot as plt

これにはpltという別名をつけました。では、この2つのライブラリを使ってみましょう。

import numpy as np
import matplotlib.pyplot as plt

x = np.linspace(0, np.pi * 2, 100)
y = np.sin(x)
plt.plot(x,y)
plt.show()

sin波のグラフが出力されました。たった6行のプログラムでグラフが描けるのです!

このプログラムの中身は今は理解しなくても構いません。重要なのは、NumPyの関数を使うときはnp.sin()のように頭に別名.をつけていることです。matplotlibの関数についても、plt.plot()のようになっています。

課題

プログラムの一部を変更して、cos波を描いてみましょう。

グラフの体裁(初級)

上で出力されたグラフは実験結果として不十分です。レポートに貼り付けるグラフとして体裁を整えます。

まずは、plt.show()の前までのプログラムを書きます。上ではを描いたので、今度はを描いてみましょう。プログラムの一部を以下のように変更します。

x = np.linspace(0, np.pi * 2, 100)
y = np.sin(x * 2)
plt.plot(x,y)

軸ラベルをつける

まずはx軸とy軸がなにか説明しましょう。今回はx軸ラベルを"Time[ms]"とします。

plt.xlabel("Time[ms]")

y軸ラベルは"Voltage[V]"とします。

plt.ylabel("Voltage[V]")

このあとに

plt.show()

するとx軸とy軸のラベルが追加されました。

凡例をつける

これらに加えて、このグラフがなんのグラフなのかを説明する凡例もつけます。今は1つの波形のみを表示していますが、複数の波形を同時に表示したときに役立ちます。

xyの値はすでに変数に入っているので、そのまま使います。

その後のplt.plot(x,y)に引数を追加し、以下のように記述します。これで凡例に"sin(2x)"と表示されます。

plt.plot(x, y, label="sin(2x)")

x, y軸のラベルもつけましょう。

plt.xlabel("Time[ms]")
plt.ylabel("Voltage[V]")

凡例をつけた場合、plt.show()の前に以下の命令を記述します。

plt.legend()

ここまで終わったら、

plt.show()

軸ラベルと凡例をつけたことで、グラフとして最低限必要な体裁は整いました。

プログラムの完成形を以下に示します。

import numpy as np
import matplotlib.pyplot as plt

x = np.linspace(0, np.pi * 2, 100)
y = np.sin(x * 2)

plt.plot(x, y, label="sin(2x)")

plt.xlabel("Time[ms]")
plt.ylabel("Voltage[V]")

plt.legend()
plt.show()

課題

プログラムの一部を変更して、の波を描いてみましょう。軸ラベルと凡例をつけてください。 この課題ができたら、先生に確認してもらったあと、LMSにグラフの画像を提出してください

ここからの内容は授業時間中に行う必要はありません。

グラフの体裁(発展課題)

グラフに最低限必要な情報は追加されましたが、このグラフをレポートに貼ることを考えるともう少し改善すべき点があります。

以下の点を順番に改善していきます。

  • 文字のサイズを大きくする
  • グラフ画像の解像度を上げる
  • x軸の最小値を左端、最大値を右端にする
  • 目盛りを内側にする
  • グリッドをつける

文字のサイズを大きくする

レポートにはあまり大きくグラフを貼ることはできないため、グラフ中の文字は小さく読みにくくなってしまいます。

グラフ中の全ての文字を大きくするには、import matplotlib.pyplot as pltのすぐ後に

plt.rcParams["font.size"] = 15

を追加してください。もとのフォントサイズは12なので、適切な大きさに調整してください。

グラフ画像の解像度を上げる

もとのグラフは、よく見ると解像度が荒いです。以下の設定でグラフの見た目を保ったまま高い解像度で表示できます。import matplotlib.pyplot as pltのすぐ後に追加してください。

plt.rcParams["figure.dpi"] = 150

デフォルトでは72になっています。

x軸の最小値を左端、最大値を右端にする

もとのグラフは、左端は中途半端な位置から始まり、右端も中途半端な位置で終わっています。x軸の最小値を左端、最大値を右端にしたい場合、以下の設定をしてください。必ずしも見やすくなるとは限らないので、必要に応じて設定してください。

plt.rcParams["axes.xmargin"] = 0

目盛りを内側にする

もとのグラフは、目盛りが外側になっています。一般的には内側のほうが適切です。

plt.rcParams['xtick.direction'] = 'in'
plt.rcParams['ytick.direction'] = 'in'

グリッドをつける

グラフによっては、グリッド(マス目)をつけたほうが値が読み取りやすい場合があります。 グリッドをつけない場合でも、縦軸が0のところに線を引いたほうが見やすいです。

plt.rcParams['axes.grid'] = True