特異メソッド
- jijixi's diary: 特異メソッドっぽいもの (http://jijixi.azito.com/cgi-bin/diary/index.rb?date=20061231#p06)
- jijixi's diary: Python だって結構泥縄指向 (http://jijixi.azito.com/cgi-bin/diary/index.rb?date=20061231#p05)
Rubyの特異メソッドはきちんと理解していないが、要するにクラスではなく、特定のインスタンスのみにメソッドを持たせるということ。Pythonで特異メソッド(っぽいもの?)を表現するには以下の方法。
>>>class C: pass ... >>> o = C() >>> def foo(self): ... return 'foo' ... >>> def bar(): ... return 'bar' ... >>> C.foo = foo # もしくは、setattr(C, 'foo', foo)でもOK >>> o.bar = bar # 特異メソッドっぽいもの >>> o.foo() 'foo' >>> o.bar() 'bar' >>> >>> import inspect >>> inspect.ismethod(o.foo), hasattr(o.foo, 'im_self') (True, True) >>> inspect.ismethod(o.bar), hasattr(o.bar, 'im_self') (False, False)
関数fooはcの時点でbound methodとなり第一引数を要求しない。同様にインスタンスオブジェクトにメソッドを追加するには、barのように第一引数を取り除いた状態で定義してあげる。これで、特異メソッドっぽいものが表現可能だが、barの中でoを参照できない。fooの中ではselfで参照できる。
またinspectしている例から分かるように、barはoのインスタンスメソッドというより、属性barがたまため関数だったというだけ。つまりbarはインスタンスメソッドではない。
>>> def baz(self): ... return self ... >>> o.baz = baz >>> o.baz(o) <__main__.C instance at 0x014AE468>
のように、第一引数として自分自身を渡してあげれば呼び出し基のインスタンスオブジェクトがメソッド内で使えるが分かりづらい。