decoration重用另一个decorator的实现

2024-05-23 15:25:58 发布

您现在位置:Python中文网/ 问答频道 /正文

我实现了一个memoize修饰符,它允许缓存函数。缓存键包含函数参数。类似地,cached装饰器缓存函数,但忽略参数。代码如下:

class ApplicationCache (Memcached):

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

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

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

        return hashed.hexdigest ()

memoize修饰符:由于python2.x吸收了w.r.t.完全限定的函数名,我只需强制用户提供合理的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装饰器:它几乎是memoize的逐字副本,只有一个例外,make_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实现在构建键时只忽略了参数(但在调用修饰函数时显然不是)。你知道吗


Tags: key函数nameselfnone参数makereturn
1条回答
网友
1楼 · 发布于 2024-05-23 15:25:58

我将去掉name参数,并提供键函数作为参数:

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__)

相关问题 更多 >