問題は、独自の呼び出し可能クラスを定義してから、それをメソッドとして使用しようとしたことです。関数を属性として使用する場合、属性として関数にアクセスすると__get__
、関数自体以外のもの (バインドされたメソッド) を返すメソッドが呼び出されます。を定義せずに独自のクラスが__get__
ある場合、暗黙的に を渡さずにインスタンスを返すだけself
です。
記述子について詳しくない場合は、 http://docs.python.org/reference/datamodel.html#descriptorsでいくつか説明されています。、、およびメソッド__get__
は、オブジェクトを属性として操作する方法を変更します。__set__
__delete__
関数として実装memoize
し、関数が既に持っている組み込みの__get__
魔法を使用することができます
import functools
def memoize(f):
@functools.wraps(f)
def memoized(*args, _cache={}):
# This abuses the normally-unwanted behaviour of mutable default arguments.
if args not in _cache:
_cache[args] = f(*args)
return _cache[args]
return memoized
または、次の行に沿ってクラスを変更することによって
import functools
class Memoize(object): #inherit object
def __init__(self, function):
self.function = function
self.memoized = {}
def __call__(self, *args): #don't accept kwargs you don't want.
# I removed "hash = args" because it shadowed a builtin function and
# because it was untrue--it wasn't a hash, it was something you intended for
# Python to hash for you.
try:
return self.memoized[args]
except KeyError:
self.memoized[args] = self.function(*args)
return self.memoized[args]
def __get__(self, obj, type):
if obj is None: #We looked up on the class
return self
return functools.partial(self, obj)
渡す引数のいずれかが変更可能である場合、これらの両方がチョークすることに注意してください (まあ、技術的にはハッシュ不可能です)。これはあなたのケースに適しているかもしれませんが、ハッシュできないケースにも対処したいかもしれませargs
ん。