Pythonクイズの回答(特異メソッド)
- mopemopeのおらっちゃ富山県民やちゃあ: Pythonクイズ (http://d.hatena.ne.jp/mopemope/20081017/p1)
Python 2.5.2 (r252:60911, Feb 21 2008, 13:11:45) [MSC v.1310 32 bit (Intel)] on win32 Type "help", "copyright", "credits" or "license" for more information. >>> import new >>> class A(object):pass ... >>> def test(self): ... print "test" ... >>> a = A() >>> a.test = new.instancemethod(test, a, a.__class__) >>> a.test <bound method A.test of <__main__.A object at 0x00D60F90>> >>> a.test() test >>> b = A() >>> b.test() Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: 'A' object has no attribute 'test'
new.pyの中でimportしているtypes.pyのソースを見ると以下のようなことをやっている。
>>> class _C: ... def _m(self): pass ... >>> _x = _C() >>> a.test = type(_x._m)(test, a, a.__class__) >>> a.test() test >>> type(_x._m) <type 'instancemethod'>
ここでinstancemethod型をtype(_x._m)で取得し、instancemethod型のコンストラクタを呼び出している。シグネチャは、help(_x._m)で表示されるが
instancemethod(function, instance, class)
で、インスタンスメソッドオブジェクトが作成される。それをインスタンスaのtest属性にバインドする。クラスAの属性は変更していないので、インスタンスbからはサーチされない。もちろんクラスAにバインドするならunbound methodを用いる必要がある。
追記(2008/10/19):
- mopemopeのおらっちゃ富山県民やちゃあ: Pythonクイズの答え (http://d.hatena.ne.jp/mopemope/20081017/p2)
newモジュールは3.0でなくなってしまうのでtypesを使う方を回答としています。
知らなかった。
実際これらtypeからインスタンス生成を生成するコードはCで書かれています。
Cで実装されているのであればいくらでも機能を追加できる。typeもdirと同じで魔法の関数だなあ。