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

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

文章目录


一、关于 cached-property

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


相关链接资源


关键功能特性

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

二、安装

shell 复制代码
pip install cached-property

三、使用指南


1、基础用法

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

python 复制代码
class Monopoly:

    def __init__(self):
        self.boardwalk_price = 500

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

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

python 复制代码
>>> monopoly = Monopoly()
>>> monopoly.boardwalk
550
>>> monopoly.boardwalk
600

转换为缓存属性:

python 复制代码
from cached_property import cached_property

class Monopoly(object):

    def __init__(self):
        self.boardwalk_price = 500

    @cached_property
    def boardwalk(self):
        self.boardwalk_price += 50
        return self.boardwalk_price

测试效果(值被缓存):

python 复制代码
>>> monopoly = Monopoly()
>>> monopoly.boardwalk
550
>>> monopoly.boardwalk  # 缓存生效
550

2、手动清除缓存

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

python 复制代码
>>> del monopoly.__dict__['boardwalk']
>>> monopoly.boardwalk  # 重新计算
600

3、线程安全版本

多线程环境下使用 threaded_cached_property

python 复制代码
from cached_property import threaded_cached_property

class Monopoly:

    def __init__(self):
        self.boardwalk_price = 500

    @threaded_cached_property
    def boardwalk(self):
        sleep(1)
        self.boardwalk_price += 50
        return self.boardwalk_price

多线程测试:

python 复制代码
>>> 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、异步支持

缓存异步属性:

python 复制代码
from cached_property import cached_property

class Monopoly:

    def __init__(self):
        self.boardwalk_price = 500

    @cached_property
    async def boardwalk(self):
        self.boardwalk_price += 50
        return self.boardwalk_price

异步调用示例:

python 复制代码
>>> 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)

设置缓存自动失效时间:

python 复制代码
from cached_property import cached_property_with_ttl

class Monopoly(object):

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

测试效果:

python 复制代码
>>> 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(日)

相关推荐
流烟默41 分钟前
基于Optuna 贝叶斯优化的自动化XGBoost 超参数调优器
人工智能·python·机器学习·超参数优化
海琴烟Sunshine43 分钟前
leetcode 263. 丑数 python
python·算法·leetcode
AI视觉网奇1 小时前
yolo 获取异常样本 yolo 异常
开发语言·python·yolo
程序员爱钓鱼1 小时前
Python编程实战 面向对象与进阶语法 迭代器与生成器
后端·python·ipython
程序员爱钓鱼1 小时前
Python编程实战 面向对象与进阶语法 JSON数据读写
后端·python·ipython
TH88862 小时前
一体化负氧离子监测站:实时、精准监测空气中负氧离子浓度及其他环境参数
python
苏打水com2 小时前
0基础学前端:100天拿offer实战课(第3天)—— CSS基础美化:给网页“精装修”的5大核心技巧
人工智能·python·tensorflow
顾安r2 小时前
11.5 脚本 本地网站收藏(解封归来)
linux·服务器·c语言·python·bash
Blossom.1183 小时前
把AI“贴”进路灯柱:1KB决策树让老旧路灯自己报「灯头松动」
java·人工智能·python·深度学习·算法·决策树·机器学习
❀͜͡傀儡师3 小时前
快速定位并解决Java应用CPU占用过高问题
java·开发语言·python