6

私は装飾された機能を持っています(簡易版):

class Memoize:
    def __init__(self, function):
        self.function = function
        self.memoized = {}
    def __call__(self, *args, **kwds):
        hash = args
        try:
            return self.memoized[hash]
        except KeyError:
            self.memoized[hash] = self.function(*args)
            return self.memoized[hash]


@Memoize
def _DrawPlot(self, options):
    do something...

今、私はこのメソッドを既存のクラスに追加したいと考えています。

ROOT.TChain.DrawPlot = _DrawPlot

このメソッドを呼び出すと:

chain = TChain()
chain.DrawPlot(opts)

私が得た:

self.memoized[hash] = self.function(*args)
TypeError: _DrawPlot() takes exactly 2 arguments (1 given)

自己増殖しないのはなぜ?

4

1 に答える 1

3

問題は、独自の呼び出し可能クラスを定義してから、それをメソッドとして使用しようとしたことです。関数を属性として使用する場合、属性として関数にアクセスすると__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ん。

于 2010-03-23T16:26:42.660 に答える