Pythons lru_cache 在内部函数上似乎不起作用

2024-01-17

我正在尝试使用functools.lru_cache缓存内部函数的结果,但缓存似乎没有按预期工作。

我有一个函数执行一些逻辑,然后调用一个相当昂贵的函数。我想缓存昂贵的函数调用的结果,尽管我只是应用lru_cache到一个内部函数。不幸的是,行为并不符合预期——即使内部函数的参数相同,每次都会调用昂贵的函数。

我创建了一个(简化的)测试用例来显示行为:

import unittest
from functools import lru_cache
from unittest.mock import patch

def expensive_function(parameter: str) -> str:
    return parameter

def partially_cached(some_parameter: str) -> str:

    @lru_cache
    def inner_function(parameter: str):
        return expensive_function(parameter)

    result = inner_function(some_parameter)

    print(inner_function.cache_info())

    return result

class CacheTestCase(unittest.TestCase):

    def test_partially_cached(self):
        
        with patch(self.__module__ + ".expensive_function") as expensive_mock:

            expensive_mock.return_value = "a"

            self.assertEqual(partially_cached("a"), "a")
            self.assertEqual(partially_cached("a"), "a")

            # If the cache works, I expect the expensive function
            # to be called just once for the same parameter
            expensive_mock.assert_called_once()

if __name__ == "__main__":
    unittest.main()

(在这种情况下,我不需要内部函数,但正如我所说 - 它被简化了)

不幸的是测试失败了

python3 /scratch/test_cache.py
CacheInfo(hits=0, misses=1, maxsize=128, currsize=1)
CacheInfo(hits=0, misses=1, maxsize=128, currsize=1)
F
======================================================================
FAIL: test_partially_cached (__main__.CacheTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
[...]
AssertionError: Expected 'expensive_function' to have been called once. Called 2 times.
Calls: [call('a'), call('a')].

----------------------------------------------------------------------
Ran 1 test in 0.004s

FAILED (failures=1)

我可能对内部函数或 lru_cache 有误解,但我不确定它是什么 - 我感谢我能得到的所有帮助。


它不能按预期工作,因为inner_function每次都被重新定义partially_cached被调用,缓存版本也被调用。因此每个缓存版本仅被调用一次。

See 记忆装饰器保持存储值 https://stackoverflow.com/questions/44577679/memoizing-decorator-keeping-stored-values

此外,如果您模拟装饰函数,则需要再次应用装饰器。

See 如何模拟装饰函数 https://stackoverflow.com/questions/19812570/how-to-mock-a-decorated-function

如果您在外部级别进行装饰,或者装饰另一个提取到外部级别的函数,如果您不通过模拟破坏它,它将起作用。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Pythons lru_cache 在内部函数上似乎不起作用 的相关文章

  • 我应该使用 Python 双端队列还是列表作为堆栈? [复制]

    这个问题在这里已经有答案了 我想要一个可以用作堆栈的 Python 对象 使用双端队列还是列表更好 元素数量较少还是数量较多有什么区别 您的情况可能会根据您的应用程序和具体用例而有所不同 但在一般情况下 列表非常适合堆栈 append is
  • python multiprocessing 设置生成进程等待

    是否可以生成一些进程并将生成进程设置为等待生成的进程完成 下面是我用过的一个例子 import multiprocessing import time import sys def daemon p multiprocessing curr
  • Python 3d 绘图设置固定色阶

    我正在尝试绘制两个 3d 数组 第一个数组的 z 值在范围内 0 15 0 15 第二个来自 0 001 0 001 当我绘图时 色标自动遵循数据范围 如何设置自定义比例 我不想看到 0 001 的浅色 而应该看到 0 15 的浅色 如何修
  • MongoEngine 查询具有以列表中指定的前缀开头的属性的对象的列表

    我需要在 Mongo 数据库中查询具有以列表中任何前缀开头的特定属性的元素 现在我有一段这样的代码 query mymodel terms term in query terms 并且这会匹配在列表 term 上有一个项目的对象 该列表中的
  • 打印数字时添加千位分隔符[重复]

    这个问题在这里已经有答案了 我真的不知道这个问题的 名称 所以它可能是一个不正确的标题 但问题很简单 如果我有一个数字 例如 number 23543 second 68471243 我想要它使print 像这样 23 54368 471
  • 矩形函数的数值傅里叶变换

    本文的目的是通过一个众所周知的分析傅里叶变换示例来正确理解 Python 或 Matlab 上的数值傅里叶变换 为此 我选择矩形函数 这里报告了它的解析表达式及其傅立叶变换https en wikipedia org wiki Rectan
  • 使用 Python Oauthlib 通过服务帐户验证 Google API

    我不想使用适用于 Python 的 Google API 客户端库 但仍想使用 Python 访问 Google APIOauthlib https github com idan oauthlib 创建服务帐户后谷歌开发者控制台 http
  • 尽管我已在 python ctypes 中设置了信号处理程序,但并未调用它

    我尝试过使用 sigaction 和 ctypes 设置信号处理程序 我知道它可以与python中的信号模块一起使用 但我想尝试学习 当我向该进程发送 SIGTERM 时 但它没有调用我设置的处理程序 只打印 终止 为什么它不调用处理程序
  • Pandas 组合不同索引的数据帧

    我有两个数据框df 1 and df 2具有不同的索引和列 但是 有一些索引和列重叠 我创建了一个数据框df索引和列的并集 因此不存在重复的索引或列 我想填写数据框df通过以下方式 for x in df index for y in df
  • Django REST Framework - CurrentUserDefault 使用

    我正在尝试使用CurrentUserDefault一个序列化器的类 user serializers HiddenField default serializers CurrentUserDefault 文档说 为了使用它 请求 必须作为
  • 在 Google App Engine 中,如何避免创建具有相同属性的重复实体?

    我正在尝试添加一个事务 以避免创建具有相同属性的两个实体 在我的应用程序中 每次看到新的 Google 用户登录时 我都会创建一个新的播放器 当新的 Google 用户在几毫秒内进行多个 json 调用时 我当前的实现偶尔会创建重复的播放器
  • 每当使用 import cv2 时 OpenCV 都会出错

    我在终端上使用 pip3 install opencv contrib python 安装了 cv2 并且它工作了 但是每当我尝试导入 cv2 或运行导入了 cv2 的 vscode 文件时 在 python IDLE 上它都会说 Trac
  • 重新分配唯一值 - pandas DataFrame

    我在尝试着assign unique值在pandas df给特定的个人 For the df below Area and Place 会一起弥补unique不同的价值观jobs 这些值将分配给个人 总体目标是使用尽可能少的个人 诀窍在于这
  • 制作一份 Python 文档的 PDF 文件

    Python 官方网站提供 PDF 文档下载 但它们是按章节分隔的 我下载了源代码并构建了 PDF 文档 这些文档也是单独的 PDF 我怎么能够从源代码中的 Makefile 构建一个 PDF 文件 我认为这样阅读起来会更方便 如果连接单独
  • Firebase Firestore:获取文档的生成 ID (Python)

    我可以创建一个新文档 带有自动生成的 ID 并存储对其的引用 如下所示 my data key value doc ref db collection u campaigns add my data 我可以像这样访问数据本身 print d
  • 如何将 Django 中的权限添加到模型并使用 shell 进行测试

    我在模型中添加了 Meta 类并同步了数据库 然后在 shell 中创建了一个对象 它返回 false 所以我真的无法理解错误在哪里或者缺少什么是否在其他文件中可能存在某种配置 class Employer User Employer in
  • 根据 Pandas 中的列表选择数据框行的子集

    我有一个数据框df1并列出x In 22 import pandas as pd In 23 df1 pd DataFrame C range 5 B range 10 20 2 A list abcde In 24 df1 Out 24
  • pandas.read_csv 将列名移动一倍

    我正在使用位于的 ALL zip 文件here http www fec gov disclosurep PDownload do 我的目标是用它创建一个 pandas DataFrame 但是 如果我跑 data pd read csv
  • pytest找不到模块[重复]

    这个问题在这里已经有答案了 我正在关注pytest 良好实践 https docs pytest org en latest explanation goodpractices html test discovery或者至少我认为我是 但是
  • 如何在Python脚本中从youtube-dl中提取文件大小?

    我是 python 编程新手 我想在下载之前提取视频 音频大小 任何 YouTube 视频 gt gt gt from youtube dl import YoutubeDL gt gt gt url https www youtube c

随机推荐