[Python入門]クラスの基礎知識:Python入門(2/2 ページ)
クラスとオブジェクト、クラスの定義、インスタンス変数、__init__メソッド、インスタンスメソッドなど、クラスの基礎知識を紹介する。
__init__メソッド
メソッドとは、あるクラス(やそのインスタンス)に固有の処理を実行するために使われる関数のことであり、クラス定義の中でdef文を使って関数を定義することで、それがメソッドとして扱われるようになる。__init__メソッドはそうしたメソッドの1つだが、Pythonでは特殊な扱いをされていて、インスタンスが生成される際に、そのインスタンスごとに固有の初期化処理を行うために、このメソッドが自動的に呼び出されるようになっているのだ(他の言語のコンストラクタに似たものといえる)。
__init__メソッドの構文を以下に示す。
__init__メソッド
def __init__(self[, param]):
インスタンスの初期化処理を行うコード
selfが示すオブジェクトの初期化を行う。初期化の際に何らかのデータが必要であれば、パラメーターを介して、それらを受け渡せる。
パラメーター | 説明 |
---|---|
self | 初期化処理を行うインスタンス |
param | 初期化に必要なデータを列挙する |
__init__メソッドのパラメーター |
class定義の本体の中で、def文により関数を定義すると、それらはそのクラスのメソッドとなる。通常の関数とは異なり、その第1パラメーターは常に「self」となる。__init__メソッドの場合、パラメーターselfはその内部で初期化処理を行う対象となるインスタンスを示す。後で見る通常のメソッドは「インスタンス.メソッド(引数)」の形で呼び出すが(例:'str'.upper())、このときの「インスタンス」がselfに自動的に代入されるので、メソッド呼び出しでself自体を明示する必要はない点にも注意しよう。
第2パラメーター以降にはインスタンスの初期化に必要となるものを列挙していく。例えば、ここではX座標の値とY座標の値が必要となる。__init__メソッドは自動的に呼び出されるので、どうやって__init__メソッドのパラメーターに値を渡すのかというと、クラスのインスタンス生成時に「クラス名()」形式の関数を呼び出してその引数に指定したものが、__init__メソッドに渡されるようになっている。よって、「point1 = Point(1.0, 1.0)」のようにすれば2つの浮動小数点数値が__init__メソッドに渡されるわけだ。これを受け取るには、__init__メソッドにも追加で2つのパラメーターが必要になる。
そこで、Pointクラスのインスタンスを初期化する__init__メソッドを定義してみよう。
class Point:
def __init__(self, x=0.0, y=0.0):
self.x = x
self.y = y
ここで注意したいのは、メソッド定義本体の「self.x」「self.y」という表現だ。これらは、「初期化対象のインスタンスの属性x」「初期化対象のインスタンスの属性y」を意味している、つまり先ほどのコードで行っていた以下の処理と同様な処理をクラス定義の中に含ませたといえる。これにより、インスタンスの属性xにパラメーターxの値が、属性yにパラメーターyの値が代入される。
point1.x = 1.0
point1.y = 1.0
なお、上のコードではデフォルト引数値を指定しているので、「Point()」としてインスタンスを生成したときには、2つのパラメーターには「0.0」が渡される。
上に示したクラス定義文を新たに実行することで、以前のPointクラスではなく、新しいPointクラスが作られる。そこで、これに合わせて2つのインスタンスpoint1とpoint2も作り直してみよう。
point1 = Point(1.0, 1.0)
point2 = Point()
print(f'point1: ({point1.x}, ({point1.y})')
print(f'point2: ({point2.x}, ({point2.y})')
ここではpoint1インスタンスの生成では「Point(1.0, 1.0)」としているので、その属性(インスタンス変数)であるxとyは共に「1.0」で初期化される。一方、point2インスタンスの生成では引数を省略しているので、その属性(インスタンス変数)であるxとyは共に「0.0」で初期化される。
では、point1が示す座標「(1.0, 1,0)」とpoint2が示す座標「(0.0, 0.0)」との距離も求めてみよう。これにはmathモジュールのsqrt関数を利用する(詳細は後述)。
from math import sqrt
print(sqrt((point1.x - point2.x) ** 2 + (point1.y - point2.y) ** 2))
実行結果を示す。
あるクラスに属するオブジェクトが持つべきデータ(インスタンス変数)を明確にするには、__init__メソッドでそれらを初期化することが肝要だ。Pointクラスを例に取れば、そうすることで、そのインスタンスが必ず属性xとyを持つことが保証されるようになり、それら(の属性)を使った処理を安心して行えるようになる。
インスタンスメソッド
最後に以下の2つの処理を行うメソッド(インスタンスメソッド)を定義しよう。
- 原点からの距離を調べる
- 他の座標との距離を調べる
といっても、実はこれらは1つのメソッドにまとめられる。実際に計算を行うコードのひな型は既に上で見た通りだ。2つの座標「(x1, y1)」と「(x2, y2)」の距離は次の式で求められる。
平方根を求めるにはmathモジュールのsqrt関数が使えるので、座標を表すPointクラスのインスタンスをpoint1とpoint2とすれば、「(point1.x - point2.x) ** 2 + (point1.y - point2.y) ** 2」を引数として、この関数に渡せばその距離が求められるというわけだ(「**」はべき乗演算子)。よって、インスタンスメソッドは次のように定義できる。
from math import sqrt
class Point:
def __init__(self, x=0.0, y=0.0):
self.x = x
self.y = y
def difference(self, point=None):
if not point:
point = Point() # 原点を表すPointクラスのインスタンスを生成
return sqrt((self.x - point.x) ** 2 + (self.y - point.y) ** 2)
__init__メソッドと同様に、第1パラメーターはselfになる。「point1.difference(……)」のようにして、メソッドを呼び出したときには、selfにはpoint1オブジェクトが代入されることは覚えておこう。つまり、これはメソッド呼び出しに使われるPointクラスのインスタンスと、第2パラメーターに渡されたPointクラスのインスタンスとの距離を計算することになる。
今述べたように、第2パラメーターにはPointクラスのインスタンスを渡すが、そのデフォルト引数値に「None」が指定されている。よって、differenceメソッド呼び出しで引数を指定しなかったときには、パラメーターpointの値はNoneになる。Noneは、値が存在しないことを意味する、Pythonの特殊な組み込み定数で、ブール演算を行う際には偽(False)として扱われる。
そこで、まずはif文でパラメーターpointが偽かどうかを調べて、そうであれば原点(0.0, 0.0)を表すPointクラスのオブジェクトを作成することで、最終的には2点間の距離を求める公式を使って戻り値を計算するようにしている。こうすることで、原点からの距離と2点間の距離の両者を計算できるようにしている。もちろん、パラメーターpointが偽のときには、「sqrt(self.x ** 2 + self.y ** 2)」を計算して、そうでなければ2点間の距離を求めるようなコードにしても構わない。
実際にPointクラスのインスタンスを幾つか作成して、この計算を行ってみよう。
point1 = Point(1.0, 1.0)
point2 = Point()
point3 = Point(5, 4)
print(point1.difference(point2))
print(point1.difference())
print(point3.difference(point1))
実行結果を以下に示す。
まとめ
今回はクラスとオブジェクト、クラスの定義、インスタンス変数、__init__メソッド、インスタンスメソッドというクラスの基礎知識を紹介した。クラスが持つ属性には他にもいろいろとある。次回はそれらについて見ていくことにしよう。
今回のまとめ:クラス
- クラスはインスタンスを生成するための設計図
- Pythonのオブジェクトは全て何らかの型(クラス)に属している
- プログラマーはclass文を使って独自のクラスを定義できる
- クラスのインスタンスは「クラス名()」関数を呼び出すことで生成できる
- クラスのインスタンスは、インスタンス変数やインスタンスメソッドなどの属性を持てる
- __init__メソッドにより、インスタンス生成時に行う初期化処理を定義できる
- インスタンスメソッドを定義することで、インスタンスが持つ属性を利用した処理を実行できる
- メソッドの第1パラメーターには、その処理の対象となるインスタンスを表す「self」を置く
「Python入門」
Copyright© Digital Advantage Corp. All Rights Reserved.