Pythonのクラスをこれまで見て来た中で、アンダースコアが二つついたメソッドがありました。初期化メソッドの__init__()ですね。見覚えはあると思います。
このように、二つのアンダースコアで囲まれたメソッドを特殊メソッドと言います。
オブジェクトの振る舞いを変更したり、クラスの性質にあった動きをさせたい時に特殊メソッドを使います。
ここでは特殊メソッドについてみていこうと思います。
特殊メソッドの使い方
全部の特殊メソッドに触れることはちょっと大変なので、代表的なものを扱ってみましょう。どんなものがあるかは公式ドキュメントや書籍などを参考にしてもらうといいでしょう。
これまで__init__()を使った操作をして来ました。これは、渡された引数を使って、クラス定義で新しく作られたオブジェクトを初期化するものでした。
何か文字列を使って操作するwordというクラスを、この初期化メソッドを使って定義してみましょう。文字列を使うということで、引数にtextを準備します。
このままクラスを作るとこのように定義できます。
class word():
def __init__(self, text):
self.text = text
textに何か入ったら、このクラスはその引数を使って初期化されるわけです。
文字列の「apple」を代入してprint文で表示させてみます。(ファイル名をspecial_method.pyでAtomで実行しています)
文字列を代入してオブジェクト化し、printで呼び出しているのがわかります。
関数でメソッドを定義してみる
ここで、二つの単語を比較するメソッドを使いたいとします。単語についての大文字と小文字を区別せずに比較して、同じ文字列かどうかをTrue or Falseで判定するメソッドを作るとしましょう。
これまでの通常のやり方でやってみるならば、equal()関数をクラス内に定義することになります。次のようなコードにしてみます。
class Word():
def __init__(self, text):
self.text = text
def equal(self, some_word):
return self.text.lower() == some_word.text.lower()
このクラスを使って、apple、Apple、coupleの3つの文字を比較してみます。
それぞれの文字列を使ってそれぞれオブジェクト化し、eaualメソッドを使って比較します。
次のような呼び出しコードになるはずです。
word1 = Word("apple")
word2 = Word("Apple")
word3 = Word("triple")
print(word1.equal(word2))
print(word1.equal(word3))
オブジェク化し、1つめと2つめ、一つめと3つ目が同じかどうか比較しています。
コードを実行するとこうなります。
文字列の判定ができているのがわかりますね。
特殊メソッドを使う
このequal()関数を定義して使ったメソッドを特殊メソッドを使って書き換えることにしましょう。
Pythonにはselfとオブジェクトが等しいかどうか判定する特殊メソッドの__eq__()があります。これを使って先ほどのコードを書き換えるとこうなります。
class Word():
def __init__(self, text):
self.text = text
def __eq__(self, some_word):
return self.text.lower() == some_word.text.lower()
定義部分が変わっただけですが、呼び出し方が少し変わって来ます。
次のように呼び出します。
word1 = Word("apple")
word2 = Word("Apple")
word3 = Word("triple")
print(word1 == word2)
print(word1 == word3)
オブジェクト化するまでは同じですが、上でやった場合のようにオブジェクトからメソッドを呼び出して出力するのではなく、オブジェクトそのものを比較しているのがわかります。
呼び出すとこうなります。
同じ結果が得られているのがわかります。
この場合は、比較するメソッドですから、イコール(==)で比較するのがクラスを使う時のオブジェクトの振る舞いとして合ってますよね。
このように特殊メソッドを使えば、オブジェクトの動きをクラスの性質に合わせることができるのです。
もう一つ、文字列の長さを返す特殊メソッド__len__()を定義してみましょう。
class Word():
def __init__(self, text):
self.text = text
def __eq__(self, some_word):
return self.text.lower() == some_word.text.lower()
def __len__(self): # 特殊メソッドの定義を追加
return len(self.text)
word1 = Word("apple")
print(len(word1))
appleの文字列の長さを数えてみましょう。実行するとこうなります。
文字列「apple」の長さは「5」とわかりました。
ここでは特殊メソッドを定義してlen(word1)とオブジェクトをそのまま入れましたが、通常のlen()関数を使ったならば、len(word1.text)と呼び出すことになります。
特殊メソッドを使えば、オブジェクトをそのまま操作するのでコードでの動きがわかりやすいのが理解できますね。
Pythonの特殊メソッドは、算術演算、比較演算、型変換など他にもたくさんあります。ここでは触れませんが、ドキュメントや書籍などを参考にして、どんなものが他にあるか見ておくのもいいでしょう。
別の機会にでも一つ一つ見ていこうかなとも思っています。
まとめ
Pythonのクラスを扱って来て、初期化メソッドの__init__()がこれまでも出て来ました。このようにアンダースコアが二つで囲まれたメソッドのことを、特殊メソッドと言います。
特殊メソッドを使うことで、クラスのオブジェクトの振る舞いを変更したり、クラスの性質にあった動きをオブジェクトにさせることができるので、関数を別に定義した時よりも、呼び出し操作の上で理解しやすい表現になります。
特殊メソッドは、算術演算、比較演算、型変換など色々とPythonにはあるので、どんなものがあるのか一度調べておくといいでしょう。