You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

FastAPI:如何在类可调用依赖中缓存依赖返回值?

如何在FastAPI的类形式可调用依赖中传参并实现跨端点的返回值缓存?

问题场景与现象

你编写了如下FastAPI示例代码,期望相同参数的类依赖能跨端点共享缓存结果:

# run.py
from functools import cache

import uvicorn
from fastapi import FastAPI, Depends

app = FastAPI()


class Dep:

    def __init__(self, inp):
        self.inp = inp

    @cache
    def __call__(self):
        print(self.inp * 100)
        return self.inp


@app.get("/a")
def a(v: str = Depends(Dep("a"))):
    return v


@app.get("/a/a")
def aa(v: str = Depends(Dep("a"))):
    return v


@app.get("/b")
def b(v: str = Depends(Dep("b"))):
    return v


@app.get("/b/b")
def bb(v: str = Depends(Dep("b"))):
    return v


def main():
    uvicorn.run(
        "run:app",
        host="0.0.0.0",
        reload=True,
        port=8000,
        workers=1
    )


if __name__ == "__main__":
    main()

预期效果:

  • 首次访问/a或/a/a时,控制台打印100个"a",后续访问不再打印
  • 首次访问/b或/b/b时,控制台打印100个"b",后续访问不再打印

实际现象:
每个端点首次访问都会打印对应日志,只有同一端点的后续访问才会触发缓存。原因是每次调用Dep("a")或Dep("b")都会创建全新的类实例,每个实例的__call__方法缓存相互独立,而FastAPI自带的依赖缓存仅作用于同一端点的重复调用。

类形式依赖的解决方案

要实现类依赖传参且跨端点共享缓存,核心是让相同参数的Dep实例复用,而非每次新建。以下是两种可行方案:

方案一:通过类方法+缓存管理实例

# run.py
from functools import cache
import uvicorn
from fastapi import FastAPI, Depends

app = FastAPI()

class Dep:
    # 缓存类实例,相同inp参数返回同一个实例
    @classmethod
    @cache
    def get_instance(cls, inp):
        return cls(inp)

    def __init__(self, inp):
        self.inp = inp

    @cache
    def __call__(self):
        print(self.inp * 100)
        return self.inp


@app.get("/a")
def a(v: str = Depends(Dep.get_instance("a"))):
    return v


@app.get("/a/a")
def aa(v: str = Depends(Dep.get_instance("a"))):
    return v


@app.get("/b")
def b(v: str = Depends(Dep.get_instance("b"))):
    return v


@app.get("/b/b")
def bb(v: str = Depends(Dep.get_instance("b"))):
    return v


def main():
    uvicorn.run(
        "run:app",
        host="0.0.0.0",
        reload=True,
        port=8000,
        workers=1
    )


if __name__ == "__main__":
    main()

原理:通过get_instance类方法结合@cache,确保相同inp参数始终返回同一个Dep实例,该实例的__call__方法缓存即可跨端点生效。

方案二:重载__new__方法实现单例缓存

# run.py
from functools import cache
import uvicorn
from fastapi import FastAPI, Depends

app = FastAPI()

class Dep:
    _instances = {}

    def __new__(cls, inp):
        # 相同inp返回已存在的实例
        if inp not in cls._instances:
            cls._instances[inp] = super().__new__(cls)
        return cls._instances[inp]

    def __init__(self, inp):
        # 避免重复初始化已存在的实例
        if not hasattr(self, 'inp'):
            self.inp = inp

    @cache
    def __call__(self):
        print(self.inp * 100)
        return self.inp


@app.get("/a")
def a(v: str = Depends(Dep("a"))):
    return v


@app.get("/a/a")
def aa(v: str = Depends(Dep("a"))):
    return v


@app.get("/b")
def b(v: str = Depends(Dep("b"))):
    return v


@app.get("/b/b")
def bb(v: str = Depends(Dep("b"))):
    return v


def main():
    uvicorn.run(
        "run:app",
        host="0.0.0.0",
        reload=True,
        port=8000,
        workers=1
    )


if __name__ == "__main__":
    main()

原理:通过__new__方法控制实例创建逻辑,相同inp直接返回已缓存的实例,确保Dep("a")每次调用都得到同一个对象,进而让__call__的缓存跨端点共享。

对比函数式方案

你实现的函数式依赖方案是可行的,通过外层@cache的dep函数返回同一个sub_dep函数,确保相同inp对应的依赖函数复用。类方案的优势在于当依赖需要维护更多状态或方法时,结构会更清晰易扩展。

内容的提问来源于stack exchange,提问作者Amin Ba

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 20:58:19