当前位置: 首页 > news >正文

cached-property - 类属性缓存装饰器

本文翻译整理自:https://github.com/pydanny/cached-property

文章目录

    • 一、关于 cached-property
      • 相关链接资源
      • 关键功能特性
    • 二、安装
    • 三、使用指南
      • 1、基础用法
      • 2、手动清除缓存
      • 3、线程安全版本
      • 4、异步支持
      • 5、缓存超时(TTL)
    • 四、致谢


一、关于 cached-property

cached-property 是一个用于缓存类属性的装饰器工具。


相关链接资源

  • github : https://github.com/pydanny/cached-property
  • PyPI : https://pypi.python.org/pypi/cached-property
  • Python 3.8+ 内置实现 : https://docs.python.org/3.12/library/functools.html#functools.cached_property
  • 问题跟踪 : https://github.com/pydanny/cached-property/issues/16

关键功能特性

  • 快速简便地缓存耗时或计算密集型的类属性
  • 支持 Python 2 和 3(Python 3.8+ 已内置类似功能)
  • 提供线程安全版本 threaded_cached_property
  • 支持异步属性缓存
  • 可设置缓存超时时间(TTL)

二、安装

pip install cached-property

三、使用指南


1、基础用法

定义包含昂贵计算属性的类:

class Monopoly:def __init__(self):self.boardwalk_price = 500@propertydef boardwalk(self):# 模拟耗时操作(如数据库查询或API调用)self.boardwalk_price += 50return self.boardwalk_price

测试效果(每次访问属性值都会变化):

>>> monopoly = Monopoly()
>>> monopoly.boardwalk
550
>>> monopoly.boardwalk
600

转换为缓存属性:

from cached_property import cached_propertyclass Monopoly(object):def __init__(self):self.boardwalk_price = 500@cached_propertydef boardwalk(self):self.boardwalk_price += 50return self.boardwalk_price

测试效果(值被缓存):

>>> monopoly = Monopoly()
>>> monopoly.boardwalk
550
>>> monopoly.boardwalk  # 缓存生效
550

2、手动清除缓存

通过删除实例字典中的属性来清除缓存:

>>> del monopoly.__dict__['boardwalk']
>>> monopoly.boardwalk  # 重新计算
600

3、线程安全版本

多线程环境下使用 threaded_cached_property

from cached_property import threaded_cached_propertyclass Monopoly:def __init__(self):self.boardwalk_price = 500@threaded_cached_propertydef boardwalk(self):sleep(1)self.boardwalk_price += 50return self.boardwalk_price

多线程测试:

>>> from threading import Thread
>>> threads = []
>>> for x in range(10):
>>>     thread = Thread(target=lambda: monopoly.boardwalk)
>>>     thread.start()
>>>     threads.append(thread)
>>> [t.join() for t in threads]
>>> assert monopoly.boardwalk == 550  # 确保线程安全

4、异步支持

缓存异步属性:

from cached_property import cached_propertyclass Monopoly:def __init__(self):self.boardwalk_price = 500@cached_propertyasync def boardwalk(self):self.boardwalk_price += 50return self.boardwalk_price

异步调用示例:

>>> async def print_boardwalk():
...     monopoly = Monopoly()
...     print(await monopoly.boardwalk)
...     print(await monopoly.boardwalk)  # 使用缓存值
>>> asyncio.get_event_loop().run_until_complete(print_boardwalk())
550
550

注:异步版本不适用于多线程环境。


5、缓存超时(TTL)

设置缓存自动失效时间:

from cached_property import cached_property_with_ttlclass Monopoly(object):@cached_property_with_ttl(ttl=5)  # 5秒后缓存失效def dice(self):return random.randint(2,12)

测试效果:

>>> monopoly = Monopoly()
>>> monopoly.dice
10
>>> monopoly.dice  # 5秒内使用缓存
10
>>> sleep(6)      # 等待缓存过期
>>> monopoly.dice  # 重新计算
3

注:TTL 功能可能存在缓存清除不彻底的问题。


四、致谢

  • 感谢 Pip、Django、Werkzeug 等项目的类似实现
  • Reinout Van Rees 推荐原始装饰器方案
  • @tinche 提供线程安全解决方案
  • @bcho 贡献 TTL 功能

伊织 xAI 2025-04-27(日)

相关文章:

  • 再学GPIO(二)
  • Milvus(8):密集向量、二进制向量、稀疏向量
  • 【Jupyter 启动时如何指定目录】
  • 《C和C++安全编码》课程笔记——第六章 并发
  • C++23 std::move_only_function:一种仅可移动的可调用包装器 (P0288R9)
  • 常用第三方库:sqflite数据库应用
  • 深入解析MyBatis-Plus中的lambdaUpdate与lambdaQuery
  • clickhouse#复制修改数据
  • 深度解析:Web Crawling与Web Scraping的区别与联系
  • 玩转OurBMC第十八期:iKVM特性浅讲
  • Pycharm(十七)生成器
  • 案例分享(九):Hadoop分布式集群部署(三节点)
  • 基于STM32、HAL库的HX710A模数转换器ADC驱动程序设计
  • 系统架构师---基于规则的系统架构
  • 海关 瑞数 后缀分析 rs
  • java16
  • AI赋能守护行车安全新防线,基于YOLOv5全系列【n/s/m/l/x】参数模型开发构建驾驶车辆场景下驾驶员疲劳分心驾驶行为智能检测预警系统
  • 泰迪杯实战案例超深度解析:运输车辆安全驾驶行为分析与安全评价系统设计
  • 关于IDEA的循环依赖问题
  • AI 发展历史与关键里程碑_附AI 模型清单及典型应用场景以及物流自动化适合的模型选择
  • 四川在浙江公开招募200名退休教师,赴川支教帮扶
  • 恒瑞医药赴港上市获证监会备案,拟发行不超8.15亿股
  • 中纪报:五一节前公开通报释放强烈信号,以铁律狠刹歪风邪气
  • 新任浙江省委常委、杭州市委书记刘非开展循迹溯源学习调研
  • 铜钴巨头洛阳钼业一季度净利润同比大增九成,最新宣布超30亿元收购黄金资产
  • 铜钴巨头洛阳钼业一季度净利润同比大增九成,最新宣布首度进军黄金矿产