选项 A
您可以使用链接答案中的结构,未标准化,列数 = 500 个函数中的最大参数数。还需要为函数名添加一列。
然后你可以做一个SELECT * FROM expensive_func_results WHERE func_name = 'calc_regress' AND arg1 = ind_key AND arg2 = dep_key and arg3 = count等。
当然,这不是一个很好的设计。对于使用较少参数调用的相同函数,需要忽略具有空值/不匹配的列;否则你会得到多个结果行。
选项 B
将表/结构创建为func_name、arguments、result,其中“参数”始终是 kwargs 字典或位置参数,但每个条目不混合。即使将 kwargs 字典存储为字符串,其中的键-> 值的顺序也是不可预测/一致的,即使它是相同的参数。因此,您需要先订购它,然后再转换为字符串并存储它。当您想要查询时,您将使用SELECT * FROM expensive_func_results WHERE func_name = 'calc_regress' AND arguments = 'str(kwargs_dict)',其中str(kwargs_dict) 是您将以编程方式设置的内容。它也可以设置为inspect.getargspec(或inspect.getcallargs)的结果,但您必须检查一致性。
除非您为查询提供所有参数或与LIKE 部分匹配,否则您将无法对参数组合进行查询。
选项 C
一直标准化:一张表func_calls 为func_name、args_combo_id、arg_name_idx、arg_value。表的每一行都将为该函数的调用参数的一个组合存储一个参数。另一个表func_results 为func_name、args_combo_id、result。您还可以进一步规范化 func_name 以映射到 func_id。
在这一个中,关键字 args 的顺序无关紧要,因为您将执行内部联接来选择每个参数。该查询必须以编程方式构建或通过存储过程完成,因为获取所有参数所需的连接数由参数数决定。您上面的函数有 3 个参数,但您可能有另一个有 10 个参数。arg_name_idx 是“参数名称或索引”,因此它也适用于混合 kwargs + args。在calc_regress(ind_key=1, dep_key=2, count=30) 和calc_regress(1, 2, 30) 等情况下可能会出现一些重复(以及calc_regress(1, 2),默认值为count args_combo_id 会有所不同,但结果显然是相同的。同样,inspect 模块可能会在这方面有所帮助。
[编辑] PS:此外,对于func_name,您可能需要使用完全限定名称以避免包中的模块之间发生冲突。装饰器也可能会干扰它;没有deco.__name__ = func.__name__ 等。
PPS:如果将对象传递给正在数据库中记忆的函数,请确保它们的 __str__ 是有用且可重复/一致的,可以存储为 arg 值。
这种特殊情况不需要您从数据库中的 arg 值重新创建对象,否则,您需要像 __repr__ was intended to be 那样制作 __str__ 或 __repr__(但不是一般完成):
这应该看起来像一个有效的 Python 表达式,可用于重新创建具有相同值的对象(给定适当的环境)。