メソッドをstatic/instanceで呼び出せるようにするデコレータ

pygeocoderのソースで使われてたのをメモ

import functools

# this decorator lets me use methods as both static and instance methods
class omnimethod(object):
    def __init__(self, func):
        self.func = func

    def __get__(self, instance, owner):
        return functools.partial(self.func, instance)


このデコレータを適用されたメソッドは、instanceメソッドとしてもstaticメソッドとしても呼べるようになる。
staticメソッドとして呼ばれた場合、selfはNoneになる

class Sample(object):
    @omnimethod
    def sample(self):
        print "sample called"

Sample().sample()
# => sample called
Sample.sample()
# => sample called


pygecoderの例

# coding=utf-8
from pygeocoder import Geocoder

address = u'Japan, Tokyo, Toshima, Nishiikebukuro'

print Geocoder().geocode(address, language="ja")
# => 日本, 東京都豊島区西池袋
print Geocoder.geocode(address, language="ja")
# => 日本, 東京都豊島区西池袋


デコレータの__get__の引数のinstanceは、instanceメソッドとして呼ばれた場合は、そのクラスのinstanceになるが、staticメソッドとして呼ばれた場合はNoneになる。
selfは常にデコレータクラスのインスタンス
ownerはメソッドが所属しているクラスである

    def __get__(self, instance, owner):
        return functools.partial(self.func, instance)