python cache缓存模块

2022-10-02 10:05:44

这种方法下要缓存的函数只能写作类函数,因为需要继承cacheable类。不知是否有什么改进方法?

from datetime import datetime

def cached(time):
    def make_cacheable(func):
        func.should_be_cached = True
        func.time_out = time
        return func
    return make_cacheable

class Cacheable(object):
    __CACHE__ = {}

    def cache_that(self, func):

        def wrapper(*args, **kw):

            name = "%s%r%r" % (func.__name__, args, kw)

            if name not in self.__CACHE__ or ( datetime.today() - self.__CACHE__["time"] ).total_seconds() > func.time_out:
                self.__CACHE__[name] = func(*args, **kw)
                self.__CACHE__["time"] = datetime.today()

            return self.__CACHE__[name]

        wrapper.__name__ = func.__name__

        return wrapper
    
    #内置函数。类中的函数每次被调用时,都是先通过该函数找到函数名对应的函数,再执行
    def __getattribute__(self, attr):
        function = super(Cacheable, self).__getattribute__(attr)

        if attr != 'cache_that' and callable(function) and hasattr(function, 'should_be_cached'):
            return self.cache_that(function)
        return function

class monitor(Cacheable):
    def __init__(self):
        pass
    
    @cached(100)
    def fetch_list(self):
        list = []
        #connect db and get list
        return list

顺便说说装饰器。

网上很多都说如果函数b装饰a,那么调用a就等于调用b(a)。但这种是在装饰器没有参数的前提下。当装饰器有参数时,被装饰的函数就不是相当于传递参数那样传递的了。

具体的机理我也不太懂,反正如果装饰器有参数的话,是需要在装饰器的内部再定义一个函数,然后返回这个函数。这个函数的唯一参数就是被装饰的函数名。如果该函数又需要有参数,那么就有需要在其内部定义一个函数,直到函数没有参数。注意,不是调用这个函数而是返回这个函数,因为调用的话是需要在函数名后加 () 的。而正如我上面的代码中,make_cacheable后面不带括号。

而如果被装饰的函数是带有参数的话,那么就像上面代码的cache_that一样,内部定义一个函数来接收被装饰函数的参数。
wrapper.__name__ = func.__name__的作用和@functools.warp(func)一样,是为了让函数返回时的名字不变,还是被装饰的函数的名字

如果装饰器是类,那么调用被装饰函数时就会先生成一个装饰类。

但是如果装饰器是类内函数呢?也会先生成一个装饰类,然后调用这个函数?

  • 作者:moom_ommo
  • 原文链接:https://blog.csdn.net/moom_ommo/article/details/93355590
    更新时间:2022-10-02 10:05:44