Pythonで特異メソッド
メソッドは普通class文の中で定義して、そのクラスのインスタンスはみんな同じメソッドを共有するものですが、特定のインスタンスだけための特注品のメソッドを、特異メソッドと言います。
Rubyには特異メソッドのための構文がありますが、Pythonにはありません。
しかし、Pythonでは特異メソッドは不可能・・・というわけではありません。
それにはnew.instancemethodを使います。
import new class A(object): def __init__(self, n): self.n = n def spam(self, x): return self.n*x + 2 a1 = A(3) a1.spam = new.instancemethod(spam, a1, A) print a1.spam # => <bound method A.spam of <__main__.A object at 0x00B014D0>> print a1.spam(3) # => 11 a2 = A(3) print a2.spam(3) # AttributeErrorが発生
a1にspamメソッドがバッチリ追加されています。a2はもとのままです。ちなみにRubyのようにstrやintにまで特異メソッドを追加する事は出来ないので悪しからず。
ところで、一々
foo.bar = new.instancemethod(bar, foo, Klass)
と書くのは面倒なので、デコレータにしてしましょう。
import new def singletonmethod(obj): def f(function): m = new.instancemethod(function, obj, type(obj)) setattr(obj, function.__name__, m) return function return f class A(object):pass a1 = A(3) @singletonmethod(a) def spam(self, x): return 3*x + 2 print a1.spam # => <bound method A.spam of <__main__.A object at 0x00B014D0>> print a1.spam(3) # => 11 a2 = A(3) print a2.spam(3) # AttributeErrorが発生
これで書きやすくなった・・・かな?
しかし「Pythonで特異メソッドはこう書く!」といった記事はそれなりに見かけますが、
「Pythonで特異メソッドを使えばこんなにハッピーですよ!」という記事は見たことがありません(僕は)。
新しいメソッドが必要なら、クラスを継承して新しいクラスを作ればいいだけなので、特異メソッドはさほど重要ではないのかもしれません。
参考