1

GetData1の呼び出しはうまく機能し、次のように出力されます。

hello 67 8.3

GetData2の呼び出しは失敗します:

TypeError: __call__() got an unexpected keyword argument 'arg1'

私のコードは

class Memoized(object):
    def __init__(self, func):
        self.func = func
        self.cache = {}

    def __call__(self, *args):
        print args
        with Locker:
            try:
                return self.cache[args]
            except KeyError:
                self.cache[args] = value = self.func(*args)
                return value


def GetData1(arg1, arg2, arg3) :
    print arg1, arg2, arg3

@Memoized
def GetData2(arg1, arg2, arg3) :
    print arg1, arg2, arg3



r = { 'arg1' : 'hello', 'arg2': 67, 'arg3' : 8.3 }
GetData1(**r)
GetData2(**r)
4

2 に答える 2

3

@Memoizedクラスは関数を置き換え(ラップ)、GetData2()それ自体でシャドウイングします。呼び出し可能であり、を取りますが、は取りませ*args**kwargs

考えられる解決策は

def __call__(self, *args, **kwargs):
    print args
    with Locker:
        kwitems = tuple(sorted(kwargs.items()))
        try:
            return self.cache[args, kwitems]
        except KeyError:
            self.cache[args, kwitems] = value = self.func(*args)
            return value

しかし、それを次のように呼び出すと、キャッシュに違いが生じます

GetData2(1, 2, 3)

またはと

GetData2(arg1=1, arg2=2, arg3=3)

または他の組み合わせ。

呼び出しパスは次のとおりです。

    wrapped GetData2()
--> Memoized.__call__()
--> self.func()
--> original GetData2()
于 2013-03-05T10:13:19.510 に答える
0

少なくとも、パラメータをに渡す方法には問題があります__call__()。-functionのをに変更してみて*argsください。これは、任意の引数のタプルを渡す代わりに、キーワード引数を辞書として渡すことを意味します。__call()__**args

class Memoized(object):
    def __init__(self, func):
        self.func = func
        self.cache = {}

    def __call__(self, **args):
        print args
        ....

これにより、次のような結果になります。

In [16]: GetData2(**r)
{'arg1': 'hello', 'arg2': 67, 'arg3': 8.3}

ただし、これにより、キャッシュルーチンの動作を期待する方法が変わる可能性があります。

于 2013-03-05T10:11:55.407 に答える