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__(). 尝试将*args-function__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 回答