IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Python知识库 -> Python缓存类实例 -> 正文阅读

[Python知识库]Python缓存类实例

本篇文章的内容主要包含

  1. 利用Python弱引用存储字典缓存类的实例,让参数相同的实例不用重复生成
  2. 略过复杂的通用化代码编写,利用Python自带库来缓存实例和方法对象

在Python的许多库中都有缓存实例的例子,比如logging模块的Logger类实例

import logging


a = logging.getLogger("abc")
b = logging.getLogger("abc")

print(a is b)   # True

弱引用(weakref)通常用于缓存或映射数据量较大的对象,当你使用python字典存放例如key为name,value为一个很大的图像对象,或者反过来,引用和修改这个图像对象时始终是“实时的”,因为它实际的存在字典中。但是利用弱引用中的WeakKeyDictionaryWeakValueDictionary,你引用这个图像时只需要使用它的名字即可,它不需要占用很大的空间来存储,实际上弱引用就是一个对象指针。

创建实例缓存的一种方式是写一个方法,每次都通过这个方法访问实例

import weakref


class 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] = instance
        return instance
    else:
        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次调用参数相同的Person只实例了一次

看到这里很容易联想到使用装饰器来简化代码

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] = instance
        else:
            instance = _cache_instance[name]
        return instance
    return inner


@instance_cache
class Person:
    def __init__(self, name):
        print("person initializing")
        self.name = name


def 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

输出在期望之内,但这个装饰器要实现到更通用化还是不够,想要把存入的参数通用化作为键并且适用于不同的类实例和方法并不是一件简单的事情,幸好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_name
        self.last_name = last_name

    def set_last_name(self, name):
        self.last_name = name


def test():
    # 测试相同参数的实例是否会重复生成
    p1 = Person("abc", "d")
    p2 = Person("abc", "d")
    print(p1 is p2)
    p3 = Person("abc", "d")
    print(p2 is p3)


def test1():
    # 测试较复杂的参数的实例是否会重复生成
    import json
    d1 = {"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():
    # 测试实例发生改变后的情况
    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

输出一切都是我们所期望的,而且不管是类方法还是普通的函数,都可以使用lru_cache来实现对象方法的缓存,此外lru_cache还支持缓存大小限制(maxsize)和严格的参数类型匹配校验(typed)以及提供被装饰的对象方法以缓存的清除和信息查看等方法

@lru_cache
def function():
    print("call function")
    return 123


def test3():
    # 只会调用一次function
    f = function()
    f2 = function()
    # 缓存的参数信息
    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知识库 最新文章
Python中String模块
【Python】 14-CVS文件操作
python的panda库读写文件
使用Nordic的nrf52840实现蓝牙DFU过程
【Python学习记录】numpy数组用法整理
Python学习笔记
python字符串和列表
python如何从txt文件中解析出有效的数据
Python编程从入门到实践自学/3.1-3.2
python变量
上一篇文章      下一篇文章      查看所有文章
加:2022-04-04 12:06:36  更:2022-04-04 12:07:36 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年12日历 -2024/12/29 2:30:30-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码
数据统计