【问题标题】:Memoize for classes whose init has super() initializationMemoize 用于 init 具有 super() 初始化的类
【发布时间】:2017-03-08 00:52:03
【问题描述】:

这是我的 memoize 实现:

猫测试.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

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

【问题讨论】:

  • 所以你总是希望Test(x) is Test(y)x == y 时为真(或者至少在hash(x) == hash(y) 时)?

标签: python python-2.7 class memoization


【解决方案1】:

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

Test = _memoize(Test)

所以,Test 不再是一个类,它是一个函数,并且错误表明 super 不需要函数。

我不太了解您的意图,无法提出替代方案。

【讨论】:

    【解决方案2】:

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

    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__,它允许你以一种更容易在类之间共享而无需继承的方式来做类似的事情。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-07-01
      • 1970-01-01
      • 2021-11-27
      • 1970-01-01
      • 2021-03-13
      • 1970-01-01
      • 2019-02-07
      • 1970-01-01
      相关资源
      最近更新 更多