如何动态设置Python函数load_or_set_cache的返回类型?
问题描述
我有一组包含key/ID和函数的字典,这些字典用作标识符,指向特定缓存键和更新该缓存键关联数据的函数。
from typing import TypedDict, List class CacheIdentifier(TypedDict): key: str func: Callable def function_to_fetch_cache_data() -> List[str]: return ["a", "b", "c"] IDENTIFIER: CacheIdentifier = { "key": "my_cache_key", "func": function_to_fetch_cache_data }
我还有一个名为load_or_set_cache的函数,它接收一个标识符对象,功能是检查缓存键是否关联有数据:如果不存在,则使用传入的CacheIdentifier对象的func参数获取新数据并存入缓存;如果存在,则直接获取缓存数据。
def load_or_set_cache(identifier: CacheIdentifier) -> Any: # 检查缓存数据是否存在的逻辑 cached = cache.get(identifier["key"]) is not None # 补充示例判断逻辑 if not cached: cache_data = identifier["func"]() cache_key = identifier["key"] cache.set(cache_key, cache_data, TTL=3600) else: cache_key = identifier["key"] cache_data = cache.get(cache_key) return cache_data cache_data = load_or_set_cache(IDENTIFIER)
该函数返回获取到的缓存数据,数据类型取决于每个标识符中函数的返回类型。例如,若function_to_fetch_cache_data返回类型为List[str],则load_or_set_cache也应返回List[str],使cache_data的类型为List[str]。目前该函数的返回类型设为Any,请问是否可以根据传入的缓存标识符中func的返回类型动态设置load_or_set_cache的返回类型?我尝试过TypeVars,但感觉它并不适合我的需求。
解决方案
完全可以实现,你需要结合泛型TypeVar和泛型TypedDict来让类型系统自动推导返回类型。之前觉得TypeVar不合适,大概率是没搭配泛型TypedDict使用,具体修改如下:
步骤说明
- 定义一个泛型
TypeVar,用来标记函数的返回类型 - 将
CacheIdentifier改为泛型TypedDict,让它的func字段类型与这个TypeVar绑定 - 给
load_or_set_cache添加泛型参数,让函数返回类型与CacheIdentifier中func的返回类型保持一致
修改后完整代码
from typing import TypedDict, List, Callable, TypeVar, Optional # 定义泛型TypeVar,表示函数的返回类型 T = TypeVar('T') # 泛型版本的CacheIdentifier,绑定func的返回类型为T class CacheIdentifier(TypedDict, generic=T): key: str func: Callable[[], T] def function_to_fetch_cache_data() -> List[str]: return ["a", "b", "c"] # 此时IDENTIFIER的类型会被自动推导为CacheIdentifier[List[str]],无需手动标注 IDENTIFIER = { "key": "my_cache_key", "func": function_to_fetch_cache_data } # 泛型函数,返回类型与传入的CacheIdentifier中func的返回类型一致 def load_or_set_cache(identifier: CacheIdentifier[T]) -> T: # 检查缓存是否存在的示例逻辑 cached_data: Optional[T] = cache.get(identifier["key"]) if cached_data is None: cached_data = identifier["func"]() cache.set(identifier["key"], cached_data, TTL=3600) # 断言缓存数据非空,确保类型安全(也可以根据实际业务处理None场景) assert cached_data is not None return cached_data # 此时cache_data的类型会被自动推导为List[str],而非Any cache_data = load_or_set_cache(IDENTIFIER)
关键细节
- 泛型
CacheIdentifier[T]会让每个标识符的func返回类型被明确绑定,类型检查器能准确跟踪类型信息 load_or_set_cache通过泛型参数T,直接复用CacheIdentifier中func的返回类型作为自身返回类型,实现了动态匹配- 如果缓存的
get方法可能返回None,可以选择返回T | None,或者通过断言、默认值等方式处理,避免类型错误
内容的提问来源于stack exchange,提问作者Eddysanoli
相关产品推荐
相关产品推荐

