Python缓存类实例
本篇文章的內(nèi)容主要包含
在Python的許多庫中都有緩存實例的例子,比如logging模塊的Logger類實例
import logginga = logging.getLogger("abc") b = logging.getLogger("abc")print(a is b) # True弱引用(weakref)通常用于緩存或映射數(shù)據(jù)量較大的對象,當你使用python字典存放例如key為name,value為一個很大的圖像對象,或者反過來,引用和修改這個圖像對象時始終是“實時的”,因為它實際的存在字典中。但是利用弱引用中的WeakKeyDictionary和WeakValueDictionary,你引用這個圖像時只需要使用它的名字即可,它不需要占用很大的空間來存儲,實際上弱引用就是一個對象指針。
創(chuàng)建實例緩存的一種方式是寫一個方法,每次都通過這個方法訪問實例
import weakrefclass Person:def __init__(self, name):print("person initializing")self.name = name_cache_instance = weakref.WeakValueDictionary() # 這里應該使用全局變量,因為是共用的存儲對象def get_person(name):if name not in _cache_instance:instance = Person(name)_cache_instance[name] = instancereturn instanceelse:return _cache_instance[name]def test():q = get_person("q")e = get_person("q")print(q is e)r = get_person("q")print(e is r)if __name__ == '__main__':test()輸出
person initializing True True從輸出可以看出3次調(diào)用參數(shù)相同的Person只實例了一次
看到這里很容易聯(lián)想到使用裝飾器來簡化代碼
import weakref from functools import wraps_cache_instance = weakref.WeakValueDictionary() def instance_cache(cls_instance):@wraps(cls_instance)def inner(name, *args, **kwargs):if name not in _cache_instance:instance = cls_instance(name, *args, **kwargs)_cache_instance[name] = instanceelse:instance = _cache_instance[name]return instancereturn inner@instance_cache class Person:def __init__(self, name):print("person initializing")self.name = namedef test():q = Person("abc")e = Person("abc")print(q is e)r = Person("abc")print(e is r)if __name__ == '__main__':test()輸出
person initializing True True輸出在期望之內(nèi),但這個裝飾器要實現(xiàn)到更通用化還是不夠,想要把存入的參數(shù)通用化作為鍵并且適用于不同的類實例和方法并不是一件簡單的事情,幸好Python為我們提供了一個非常好用和方便的最近最久未使用的緩存方法functools.lru_cache
from functools import lru_cache@lru_cache() class Person:def __init__(self, fist_name, last_name=None):print("person initializing")self.first_name = fist_nameself.last_name = last_namedef set_last_name(self, name):self.last_name = namedef test():# 測試相同參數(shù)的實例是否會重復生成p1 = Person("abc", "d")p2 = Person("abc", "d")print(p1 is p2)p3 = Person("abc", "d")print(p2 is p3)def test1():# 測試較復雜的參數(shù)的實例是否會重復生成import jsond1 = {"a": [1, 2], "b": "3"}d2 = {"a": [1, 2], "b": "3"}d3 = {"a": [1, 2], "b": "3"}d1 = json.dumps(d1)d2 = json.dumps(d2)d3 = json.dumps(d3)p1 = Person("abc", d1)p2 = Person("abc", d2)print(p1 is p2)p3 = Person("abc", d3)print(p2 is p3)def test2():# 測試實例發(fā)生改變后的情況p1 = Person("abc")p2 = Person("abc")print(p1 is p2)p2.set_last_name("def")print(p1 is p2)if __name__ == '__main__':# test()# test1()test2()輸出
person initializing True True輸出一切都是我們所期望的,而且不管是類方法還是普通的函數(shù),都可以使用lru_cache來實現(xiàn)對象方法的緩存,此外lru_cache還支持緩存大小限制(maxsize)和嚴格的參數(shù)類型匹配校驗(typed)以及提供被裝飾的對象方法以緩存的清除和信息查看等方法
@lru_cache def function():print("call function")return 123def test3():# 只會調(diào)用一次functionf = function()f2 = function()# 緩存的參數(shù)信息print(function.cache_parameters())# 緩存信息print(function.cache_info())# 清除緩存function.cache_clear()print(function.cache_info())if __name__ == '__main__':test3()輸出
call function CacheInfo(hits=1, misses=1, maxsize=128, currsize=1) {'maxsize': 128, 'typed': False} CacheInfo(hits=0, misses=0, maxsize=128, currsize=0)總結
以上是生活随笔為你收集整理的Python缓存类实例的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 第一周:深度学习引言(Introduct
- 下一篇: 数据结构之图:加权无向图与寻找最小生成树