对init初始化为super()的类进行Memoize

时间:2016-10-25 20:20:15

标签: python python-2.7 class memoization

这是memoize的实现:

cat test.py

def _memoize(obj):
    cache = obj.cache = {}

    @functools.wraps(obj)
    def memoizer(*args, **kwargs):
        key = str(args) + str(kwargs)
        if key not in cache:
            cache[key] = obj(*args, **kwargs)
        return cache[key]
    return memoizer

@_memoize
class Test(object):
    def __init__(self, arg1):
        super(Test, self).__init__()
        self.arg = arg1
        print "init executed for " + arg1

    def authenticate(self):
        print self.arg

t1 = Test('a')

当我运行此操作时,我收到以下错误:

$ python test.py

Traceback (most recent call last):
  File "test.py", line 23, in <module>
    t1 = Test('a')
  File "test.py", line 9, in memoizer
    cache[key] = obj(*args, **kwargs)
  File "test.py", line 16, in __init__
    super(Test, self).__init__()
TypeError: super() argument 1 must be type, not function

您能否建议如何解决此错误?

2 个答案:

答案 0 :(得分:1)

functools.wraps是函数包装器的便利,使用装饰器是like wrapping Test in that function call;

Test = _memoize(Test)

所以,Test不再是一个类,它是一个函数,因为错误表明super不想要一个函数。

我不明白你的意图足以提出替代方案。

答案 1 :(得分:1)

在memoizer功能中,您需要创建一个新类型;你正在创建并返回一个函数,这样你就可以将你的类变成一个函数了。完成你要做的事情的一种更简单的方法是覆盖__new__,它允许你在分配对象之前拦截对构造函数的调用,所以你可以这样做(简化,但你可以复制你的多个arg也在此处理):

class Test(object):
    def __init__(self, arg):
        self.x = arg

    _cache = {}
    def __new__(cls, arg):
        if arg not in _cache:
            _cache[arg] = cls(arg)
        return _cache[arg]

如果你想要更多装饰风格的东西,你可以看看__metaclass__,它允许你以一种更容易在没有继承的类之间共享的方式做类似的事情。