0

我已经实现了一个memoize装饰器,它允许缓存一个函数。缓存键包括函数参数。类似地,cached装饰器缓存了一个函数,但忽略了参数。这是代码:

class ApplicationCache (Memcached):

make_key方法:UltraJSON快速传递一个字符串,该字符串SHA512散列成一个清晰的十六进制摘要:

    def make_key (self, *args, **kwargs):

        kwargs.update (dict (enumerate (args)))
        string = ujson.encode (sorted (kwargs.items ()))
        hashed = hashlib.sha512 (string)

        return hashed.hexdigest ()

装饰器:由于memoizePython 2.x 吸收了完全限定的函数名,我只是强制用户提供一个合理的name

    def memoize (self, name, timeout=None):
        assert name

        def decorator (fn):
            @functools.wraps (fn)
            def decorated (*args, **kwargs):

                key = self.make_key (name, *args, **kwargs)
                cached = self.get (key)

                if cached is None:
                    cached = fn (*args, **kwargs)
                    self.set (key, cached, timeout=timeout)

                return cached
            return decorated
        return decorator

装饰者:它几乎是一个忽略参数的例外的cached逐字副本:memoizemake_key

    def cached (self, name, timeout=None):
        assert name

        def decorator (fn):
            @functools.wraps (fn)
            def decorated (*args, **kwargs):

                key = self.make_key (name) ## no args!
                cached = self.get (key)

                if cached is None:
                    cached = fn (*args, **kwargs)
                    self.set (key, cached, timeout=timeout)

                return cached
            return decorated
        return decorator

现在,我的问题cached是,它要求重构:它应该使用memoize并且想法是消除fn(使用functools.partial可能?)的论点,例如:

    def cached (self, name, timeout=None):

        ## Reuse the more general `memoize` to cache a function,
        ## but only based on its name (ignoring the arguments)

我实际上不确定我是否在这里过度使用 DRY 原则,以及是否可以重用,因为当前的实现cached在构建密钥时忽略参数(但显然不是在调用修饰函数时)。

4

1 回答 1

1

我会摆脱name参数并提供 key 函数作为参数:

def memoize(self, timeout=None, keyfunc=self.make_key):
    ...
    key = keyfunc(function.__name__, *args, **kwargs)
    ...

cache然后将变成:

def cache(self, timeout=None):
    return self.memoize(timeout, keyfunc=lambda f, *args, **kwargs: f.__name__)
于 2012-12-30T14:46:18.360 回答