home changes contents help options

015:特異メソッド

PythonにはRubyのような「特異メソッドのための構文」はありません。 しかし、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が発生

ちなみにRubyのように文字列や整数にまで特異メソッドを追加する事は出来ません、悪しからず。

ところで、一々

foo.bar = new.instancemethod(bar, foo, Klass)

と書くのは面倒です。 しかし、関数デコレータを使うと、短く出来ます。

#singletonmethod.py
import new

def singletonmethod(obj):
    def f(function):
        m = new.instancemethod(function, obj, type(obj)) 
        setattr(obj, function.__name__, m)
        return function
    return f

これをsingletonmethod.pyに書き込み、Pythonのパスが通った場所(C:Python26Libsite-packages等)に保存します。

以下の様に使います。

from singletonmethod import singletonmethod

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