作者: 機械伯爵
日時: 2002/4/4(16:53)
 Pythonの動作をさぐるための実験コーナー「その1」

※好奇心を満たす以外の意味は、あまり無いと思うけど・・・

 Rubyはすでにあるクラスのメソッドを追加できます。

<例>

class A
  def x()
    print "x"
  end
end

class A
  def y()
    print "y"
  end
end

 これで、クラスAにxとyというメソッドが両方定義されること
になります。

 おなじことをPythonでやると、バグります。

class A:
  def x(self):
    print "x"

class A:  # ここで、前のAが破棄される
  def y(self):
    print "y"

 これでクラスAのインスタンスからx()メソッドを呼び出すと、
 「んなもんはない」
 と、冷たくあしらわれます。

 ちなみに、最初の定義の直後のインスタンスと、再定義後のインスタンス
の情報を見てみると、おなじ名前の全く別のオブジェクト(クラス)を
参照していることがわかります。

 Rubyにはオブジェクトから独立した関数は存在しないので、クラスの拡張
ができないと、関数的なメソッドも定義できないのでこうなってるのだと思
いますが、ここらへん、思想の違いが現れてて面白いですね。

※ちなみに、Javaはこういったことができないので、クラスをモジュールの
 ように使わないと、ホントにただの関数は定義できません。

 Pythonは別段「Object」のような「最上位クラス」は存在せず、自然発生
的に適当にクラスが出来るので、そういう必然性は無いみたいです(ここら
へん、C++に近いけど、C++ではクラスメソッドは拡張できる)

 まぁ、こういうあやしいことは出来ますが・・・

class A:
  def x(self):
    print "x"

class A(A): # 再帰的自己継承(爆)
  def y(self):
    print "y"

 これで、Aにxとyの両方のメソッドが定義されるわけですが、だからと
いって、さいしょのAのインスタンスにメソッドyが追加されるわけでは
ありません。

 ただし、フィールドは別

>>> class A:
...   x = 1
...
>>> a = A()
>>> A.y = 2
>>> a.y
2
>>>

 よって、禁断の「メソッドをフィールドスロットにつっこむ」をすれ
ば、クラス拡張可能!

>>> class A:pass
...
>>> def x():print "x"
...
>>> a = A()
>>> A.x = x
>>> a.x()
x
>>>

 とはいっても、Aの内部にアクセスできない「ただひっつけただけ」なの
で、意味があるかどうかは不明・・・

   機械伯爵