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の内部にアクセスできない「ただひっつけただけ」なの
で、意味があるかどうかは不明・・・
機械伯爵