今回はシンプルなクラス定義、各種のメンバを持つクラスの定義、継承と多重継承の方法など、Python 3のクラスについて駆け足で見ていこう。
前回はリストなどの内包表記、ジェネレーター式について見た。今回はクラスとモジュールについて見ていこう。今回も動作はVisual Studio 2015の[Interactive]ウィンドウ(64bit版のPython 3.5.2)を使用している。ただし、コード例からは「>>>」プロンプトを省略して、コピー&ペーストをしやすい形にしてある(実行結果は[Interactive]ウィンドウのものとなっている)。
Pythonで最もシンプルなクラス定義は次のようになる。
class Foo:
pass
「pass」文は何もしないことを表す文だ。Pythonでは「class 〜:」の後にブロックがないとエラーとなるので、何もしないことを示すためにpass文を記述する(C#などの言語における「{}」と似たようなものといえる)。
上記のように「基底クラス」を指定していない場合、そのクラスはobject型を基底クラスとする。
クラスのインスタンスを作成するには、C#などの言語とは異なり「new」は不要で、以下のようにクラス名に続けてかっこを記述して関数的に使用する。
f = Foo() # インスタンス生成に「new」キーワードは不要
print(type(f)) # 出力結果: <class '__main__.Foo'>
組み込み関数typeの出力結果を見ると分かるように、変数fの型は「__main__.Foo」となっている。Pythonの「ライブラリレファレンス」によると、「__main__」は「トップレベルのコードが実行されるスコープの名前」である。簡単にいうと、[Interactive]ウィンドウのような対話環境でプログラマーがPythonコードを直接入力したり、コマンドラインから「python 〜.py」を入力してPythonスクリプトを実行したりすると、それらのコードは「__main__」という組み込みのスコープで実行される。よって、「<class '__main__.Foo'>」はそのスコープ内で定義されたクラスFooということになる。
なお、スコープやモジュールについては次回に詳しく説明することにしよう。
もちろん、クラスにはメンバがなければ役には立たない。以下にメンバを持つクラス定義がどうなるか、その構文を示す。
class クラス名:
クラス変数名 = ... # クラス変数
# インスタンスの初期化
def __init__(self[, パラメーターリスト]): # インスタンスの初期化を行う
self.インスタンス変数名 = ... # インスタンス変数の初期化を行う
# インスタンスメソッド
def instance_method(self[, パラメーターリスト]):
インスタンスメソッドの実装
@classmethod # クラスメソッドは「@classmethod」で修飾する
def class_method(cls[, パラメーターリスト]):
クラスメソッドの実装
@staticmethod # スタティックメソッドは「@staticmethod」で修飾する
def static_method([パラメーターリスト]):
スタティックメソッドの実装
見慣れないのは「__init__」という表記だ。__init__メソッドは、インスタンスの初期化に使われるメソッドであり(上の例であれば、「f = Foo()」としたときに__init__メソッドがあれば、インスタンスが生成された後でそれが呼び出される)、他のプログラミングにおけるコンストラクタに近い処理を行うものだ。
__init__メソッドとインスタンスメソッド(上ではinstance_method)の第1パラメーターには慣例として「self」を指定する。__init__メソッドでは「self.インスタンス変数名 = ...」のようにselfを使用して、そのインスタンスが持つインスタンス変数の初期化を行う。また、「インスタンス.メソッド(引数)」のようにしてインスタンスメソッドを呼び出すと、メソッド呼び出しに使われたインスタンスが暗黙の引数としてselfに渡される。その後ろの「パラメーターリスト」が実際のメソッド呼び出しにおける引数を受け取る。
まずは、__init__メソッドとインスタンスメソッドを持つクラスを定義してみよう*1。
*1 なお、以降のコードではメソッド定義間に空行を挟んでいる。そのため、これらのコードを[Interactive]ウィンドウに見た通りに入力していくと、空行を入力した時点でクラス定義が終了してしまう。手入力しようという場合には空行を入力しないように注意してほしい。コードをコピー&ペーストした場合には、問題なくクラス定義が行われるので、そちらをお勧めする。
class Foo:
def __init__(self, name):
self.name = name
def hello(self):
print("hello", self.name)
f = Foo("insider.net")
f.hello()
これを実行すると次のようになる。
>>> class Foo:
... def __init__(self, name):
... self.name = name
...
... def hello(self):
... print("hello", self.name)
...
>>> f = Foo("insider.net")
>>> f.hello()
hello insider.net
インスタンスメソッドの内部でインスタンス変数にアクセスするには「self.」を前置する必要があるのは、C#に慣れている方には注意が必要かもしれない。C#ではインスタンス変数へのアクセスには「this」を省略できることが多いが、Pythonではそうはいかない。あるインスタンスメソッドから、別のインスタンスメソッドを呼び出す際も同様だ。上記のクラスFooにメソッドを増やしてみよう。
class Foo:
def __init__(self, name):
self.name = name
def hello(self):
print("hello", self.name)
def bar(self):
print("instance method #2")
self.hello()
f = Foo("insider.net")
f.hello()
f.bar()
インスタンスメソッドbarからは同じクラスのインスタンスメソッドhelloを呼び出しているが、ここでも「self.hello()」のように「self.」が必要となる。「self.」を抜いて上記コードを実行した結果を以下に示す(「self.」付きの例は省略)。
>>> class Foo:
... def __init__(self, name):
... self.name = name
...
... def hello(self):
... print("hello", self.name)
...
... def bar(self):
... print("instance method #2")
... hello() # 「self.」を抜いてみた
...
>>> f = Foo("insider.net")
>>> f.hello()
hello insider.net
>>> f.bar()
instance method #2
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 8, in bar
NameError: name 'hello' is not defined
インスタンスメソッドのパラメーターリストの先頭には「self」が必要であることと、インスタンス変数やインスタンスメソッドのアクセスには「self」を介する必要があることは覚えておこう(この名前は慣例的なものだが、他のPythonプログラムを読めば、まずそうなっているし、自分のコードを他のPythonプログラマーが読むときのことを考えると、「self」とするのが強く推奨される)。
次に、クラス変数とクラスメソッドについて見てみよう。
Copyright© Digital Advantage Corp. All Rights Reserved.