6. Python スクリプトの階層構造

Python はオブジェクト指向の言語であり、いくつかの階層構造があります。 例えば、NumPy などのライブラリは、「パッケージ」と呼ばれる大きなコード群として提供されています。 また各パッケージには、「モジュール」と呼ばれる小さなコード群が複数含まれることが多くなっています。 例えば、NumPy の線形代数機能は linalg という名前のモジュールで提供されています。

さらに、各モジュールには「クラス」が定義されていることがあり、 その中に変数や関数(クラスに付属する関数はメソッドと呼ばれる)が含まれています。

クラスは、オブジェクト指向プログラミングに必要な重要な概念ですが、 発展的な内容を含むため、ここでは深くは紹介しません。 ただし多くのライブラリで用いられることが多いため、その使用法だけを簡単に紹介します。

6.1. パッケージ内・モジュール内へのアクセス

これまでNumPyの sin 関数を実行する際、np.sin() を実行しました。 これは、NumPy パッケージ内に定義されている sin 関数を呼び出すための記法です。 ここで「.」は、1つ下の階層への移動を意味するもので、この例の場合 「パッケージ名.関数名」 という形式でアクセスしていることになります。

同様に、NumPy パッケージ内の fft モジュール内の 実数に対する高速フーリエ変換 rfft を実行するためには np.fft.rfft というように 「パッケージ名.モジュール名.関数名」 と言う形式でアクセスする必要があります。

6.2. クラスの使い方 np.ndarray

クラスはオブジェクト指向の重要な概念です。 その定義を説明する前に、ここではまずその一例である np.ndarray を紹介します。

In [1]: x = np.linspace(0,1.1,12)

In [2]: x
Out[2]: 
array([ 0. ,  0.1,  0.2,  0.3,  0.4,  0.5,  0.6,  0.7,  0.8,  0.9,  1. ,
        1.1])

ここで、 x は12個の要素からなる1次元ベクトルです。

言葉の定義を少し明確にしておきましょう。 「クラス」は型名のことであり、ここで x のクラスは np.ndarray です。 一方、 xnp.ndarray 型を持つ変数です。 オブジェクト指向の言語ではこの変数のことを「オブジェクト」や「インスタンス」と呼びます。

各オブジェクトは、内部に変数や関数などの別のオブジェクトを有していることが多々有ります。 例えば np.ndarray のオブジェクトは、 アレイの大きさや次元数などを別のオブジェクトとして有しています。

In [3]: x.shape  # x の形状
Out[3]: (12,)

In [4]: x.ndim  # x の次元数
Out[4]: 1

このように、オブジェクト内部のオブジェクトには 「オブジェクト名.オブジェクト名」 というように「.」を使うことでアクセスできます。

クラスは、それ自身の値を操作する関数(メソッドと呼ぶ)を有していることも多いでしょう。 例えば np.ndarray の場合、 reshape メソッドを実行することで 12要素を持つ1次元の np.ndarray を 3x4 要素を持つ2次元行列に並び替えることができます。 このようなメソッドにも「.」を用いてアクセスできます。

In [5]: y = x.reshape(4,3)

In [6]: y.shape
Out[6]: (4, 3)

In [7]: y
Out[7]: 
array([[ 0. ,  0.1,  0.2],
       [ 0.3,  0.4,  0.5],
       [ 0.6,  0.7,  0.8],
       [ 0.9,  1. ,  1.1]])

この reshape のように、一般的にメソッドは、自分自身(ここではオブジェクト x )と、 それに加えて引数(ここでは 4, 3 )を受け取り、 何か戻り値(ここでは別のnp.ndarray型のオブジェクト y )を返す関数になっています。

本講座では、クラスをどのようにして定義するかなどは省略しますが、 クラスはデータ(上の例では x に格納されている値)と機能( reshape などのメソッド) をひとまとめにしたものであると理解できれば、外部パッケージの使用には十分でしょう。