python 閉包+弱引用 實現函數緩存

import functools
import time
import weakref
import collections

class LocalCache():

    class Dict(dict):
        def __del__(self):
            pass

    def __init__(self, maxlen=10):
        self.weak = weakref.WeakValueDictionary()  # {'key1':{}, 'key2':{}, 'key3': {}} 內嵌的字典value弱引用self.strong裏面的字典元素
        self.strong = collections.deque(maxlen=maxlen)  # 隊列中的元素是字典對象

    @staticmethod
    def nowTime():
        return int(time.time())

    def get(self, key):
        '''
        弱引用裏面取數據,強引用裏面刪除對象
        '''
        value = self.weak.get(key, None)
        if value is not None:
            expire = value[r'expire']
            if self.nowTime() > expire:
                return
            else:
                return value
        else:
            return

    def set(self, key, value):
        # to-do 判斷key是否已經存在了、判斷key是不是可hash對象

        self.weak[key] = strongRef = LocalCache.Dict(value)  # 這行代碼是重點
        self.strong.append(strongRef)

# 閉包的一種使用場景
def funcCache(expire=0):

    caches = LocalCache()  # 閉包的自由變量

    def _wrappend(func):
        @functools.wraps(func)
        def __wrappend(*args, **kwargs):
            key = str(func) + str(args) + str(kwargs)  # key是被裝飾函數的參數拼接
            result = caches.get(key)
            if result is None:
                result = func(*args, **kwargs)
                caches.set(key, {'result': result, 'expire': expire + caches.nowTime()})
                result = caches.get(key)
            return result
        return __wrappend
    return _wrappend

@funcCache(expire=3)
def test_cache(v):
    print('work 3s')
    return v

print(test_cache(1))
print(test_cache(2))
print(test_cache(1))  # 參數爲1 在上面已經有調用過了,因此這個是從緩存中取的
print(test_cache(2))  # 參數爲2 在上面已經有調用過了,因此這個是從緩存中取的

# 測試緩存超時後(4s > 3s)的效果
print('\n緩存過時後的結果:')
time.sleep(4)
print(test_cache(1))
print(test_cache(2))

 

輸出結果php

work 3s
{'result': 1, 'expire': 1626521912}
work 3s
{'result': 2, 'expire': 1626521912}
{'result': 1, 'expire': 1626521912}
{'result': 2, 'expire': 1626521912}

緩存過時後的結果:
work 3s
{'result': 1, 'expire': 1626521916}
work 3s
{'result': 2, 'expire': 1626521916}

 

弱引用參考:
https://blog.51cto.com/sleepd/1073044
https://blog.csdn.net/z_feng12489/article/details/89433878
本地緩存參考:
https://blog.csdn.net/weixin_34240520/article/details/92022464
functiontools.wraps的做用:
https://www.cnblogs.com/liuwei0824/p/10405212.htmlhtml

相關文章
相關標籤/搜索