概要
オブジェクト指向プログラミングを始めると、必ずと言っていいほど疑問となるのが、
「メソッドと関数はどう違うのか」というもの。
これに対する簡単な答えはこうだ。
プログラマが書くのが関数。pythonが自動で作ってくれるのがメソッド。
実験
まず、次のコードを実行してほしい。
>>> class クラス:
... def メソッド(self):
... return self
...
>>> type(クラス.メソッド)
すると、次の結果を得る。
<class 'function'>
これが意味するのは、今までメソッドだと思ってきた メソッド
だが、いざ型を調べてみたら、
メソッドではなく関数であることが分かってしまったというものだ。
続けて、次のコードを実行してほしい。
>>> インスタンス = クラス()
>>> type(インスタンス.メソッド)
すると、次の結果を得る。
<class 'method'>
今度は、さっきまで関数だったはずの メソッド
が、メソッドとしての型を持つ結果となった。
説明
実は、 クラスにメソッドなんてない のである。あるのは関数だけだ。
クラスからインスタンスが作られたときに、クラスの関数が インスタンスのメソッドになる だけのことなのである。
次に、これを理解するため、2通りの説明を用意した。
ひとつはクラスとインスタンスの違いをOSとコンピュータの関係になぞらえて説明するものであり、
もう一つは、形式として表れる、関数とメソッドに違いを実際に確認するものである。
インスタンスはコンピュータ。クラスはOS
まず、クラスにはチューリング完全な記述が可能である。
何故なら、クラス内の変数でメモリを、クラス内の関数でヘッダを表現できるからだ。
従って、そのクラスから作られるインスタンスはチューリングマシンとみなせる。…①
ここで、チューリングマシンは、コンピュータである。…②
①②より、インスタンスはコンピュータである。…③
また、インスタンスは、クラスにより挙動や仕様が定められている。…④
ここで、コンピュータの挙動や仕様を定めるものは、OSである。…⑤
④⑤より、インスタンスがコンピュータであれば、クラスはOSであるため、③より、クラスはOSである。…⑥
さて、OSが出来るのは、あくまでも「計算・処理方法の定義」(理論)であって、実際に計算を行い、処理を実現する(実践)ことで何らかの「機能」を提供するのはコンピュータの仕事である。…⑦
計算や処理方法の定義は、つまるところ式(と文)の集まりにより、入力を出力に変換する規則を明記したものに過ぎないため、これは理論に過ぎず、単なる「関数」である。…⑧
⑦⑧より、OSが提供するものは「関数」である。…⑨
⑦と⑨をまとめると、
OSは理論と「関数」を提供し、
コンピュータは「関数」に従って処理を実践し、「機能」を提供する。…⑩
⑥⑩より、クラスが持つのは(理論を述べた) 関数 function
であり、
インスタンス が持つのは(実践をする) 機能 method
である。
関数とメソッドは、引数も違う
関数とメソッドの形式上の最大の違いは、引数の個数である。
具体的には、 メソッドは、関数から一番最初の引数だけ奪われたもの となっている。
早速実験してみよう。
但し、ややこしいので、クラス.関数 = クラス.メソッド
という処理をしておく。
まず、メソッドである、 インスタンス.メソッド()
を実行する。
>>> インスタンス.メソッド()
<__main__.クラス object at 0x0000016996CD7610>
この メソッド
を定義した際、仮引数 self
を1つ用意していたにもかかわらず、
呼び出し時には 実引数0個となっている。
そして、戻り値を見ると、 インスタンス
が返却されている。
メソッド
では、 return self
という処理が定義されていたことから、
一番最初の仮引数 self
には インスタンス
が実引数として勝手に代入される ということが分かる。
次に、関数である クラス.関数(インスタンス)
を実行する。
>>> クラス.関数 = クラス.メソッド
>>> クラス.関数(インスタンス)
<__main__.クラス object at 0x0000016996CD7610>
これは、インスタンス.メソッド()
と同等の結果である。
実際、
>>> クラス.関数(インスタンス) is インスタンス.メソッド()
True
となる。
結論
>>> クラス.関数 = クラス.メソッド
>>> インスタンス = クラス(*a1, **ka1)
のとき、
>>> クラス.関数(インスタンス, *a2, **ka2) is インスタンス.メソッド(*a2, **ka2)
True
である。
メソッドは、pythonのシステムが「勝手に」クラス内の関数から最初の引数を奪い取り、そこにインスタンス自身を代入したものである。
つまり、メソッドは、pythonシステムが「勝手に」作った、関数の模造品なのである。
繰り返すが、メソッドは pythonシステムが作るのであり、プログラマが作るものではない。
プログラマは、あくまでも関数を作るのみである。