设计能够计算函数或从文件加载结果的应用程序
Design for application able to calculate a function or load the result from a file
我有很多文件需要用某些耗时的函数处理 f_1() ... f_n()。
因此,每次函数 f_k() 结束其工作时,我都会将 fk_processed_output 保存在文件中,以避免在未来的工作会话中重新计算。
程序必须能够动态选择是否需要计算结果或从 HDD 加载结果(如果给定的输入文件是在之前计算的)。
实现这个的好的设计是什么?
我想像这样实现每个 f_k{}:
def f_k():
if (fk_processed_output.exist()):
load_it_from_file()
else:
output = do_some_stuff()
save_to_file(output)
但我不太喜欢它,因为每个函数都重复了 if/else 模式。
有什么更好或更聪明的主意吗?还有其他提示吗?是否存在用于此目的的图书馆?
使用装饰器:
def fk_processed (fk):
filename = fk.__name__ + '_output.json'
def new_fk (*args, **kargs):
if (os.path.exists(filename)):
print("Load from file (" + fk.__name__ + ").")
output = json.load (open(filename))
else:
print("Call to function (" + fk.__name__ + ").")
output = fk (*args, **kargs)
json.dump (output, open(filename, 'w'))
return output
return new_fk
@fk_processed
def f1 ():
...
@fk_processed
def f2 ():
...
>>> f1 ()
Call to function (f1).
>>> f1 ()
Load from file (f1).
我使用 json
存储数据,因此您(大多数时候)不必担心 fk
.
返回的值的类型
请注意,如果您的 fk
的输出不总是相同,这将不起作用。在这种情况下,您必须向 fk_processed
.
添加一些额外的内容
这是一个适用于参数但不适用于关键字参数的版本(您可以根据需要修改它,只需始终以相同的顺序考虑关键字参数...)。没有很重的功能就不要用!
def fk_processed (fk):
filename = fk.__name__ + '_output.json'
def new_fk (*args):
store = {}
if (os.path.exists(filename)):
store = json.load (open(filename))
cstore = store
i = 0
while i < len(args) and str(args[i]) in cstore:
cstore = cstore[str(args[i])]
i += 1
if i != len(args):
while i < len(args) - 1:
cstore[str(args[i])] = {}
cstore = cstore[str(args[i])]
i += 1
# print('compute')
cstore[str(args[i])] = fk (*args)
cstore = cstore[str(args[i])]
json.dump (store, open(filename, 'w'))
return cstore
return new_fk
请注意,我正在将 store
字典中的参数转换为字符串,因为 JSON 只允许字符串作为键。如果您的函数参数不简单,这可能会破坏很多事情。
示例:
>>> @fk_processed
... def add (x, y): return x + y
...
>>> add (1, 2)
compute
3
>>> add (1, 3)
compute
4
>>> add (1, 2)
3
>>> add ('1', '3') # Here is the problem if you can have various types from your arguments
4 # expected '13'
我有很多文件需要用某些耗时的函数处理 f_1() ... f_n()。 因此,每次函数 f_k() 结束其工作时,我都会将 fk_processed_output 保存在文件中,以避免在未来的工作会话中重新计算。
程序必须能够动态选择是否需要计算结果或从 HDD 加载结果(如果给定的输入文件是在之前计算的)。
实现这个的好的设计是什么?
我想像这样实现每个 f_k{}:
def f_k():
if (fk_processed_output.exist()):
load_it_from_file()
else:
output = do_some_stuff()
save_to_file(output)
但我不太喜欢它,因为每个函数都重复了 if/else 模式。
有什么更好或更聪明的主意吗?还有其他提示吗?是否存在用于此目的的图书馆?
使用装饰器:
def fk_processed (fk):
filename = fk.__name__ + '_output.json'
def new_fk (*args, **kargs):
if (os.path.exists(filename)):
print("Load from file (" + fk.__name__ + ").")
output = json.load (open(filename))
else:
print("Call to function (" + fk.__name__ + ").")
output = fk (*args, **kargs)
json.dump (output, open(filename, 'w'))
return output
return new_fk
@fk_processed
def f1 ():
...
@fk_processed
def f2 ():
...
>>> f1 ()
Call to function (f1).
>>> f1 ()
Load from file (f1).
我使用 json
存储数据,因此您(大多数时候)不必担心 fk
.
请注意,如果您的 fk
的输出不总是相同,这将不起作用。在这种情况下,您必须向 fk_processed
.
这是一个适用于参数但不适用于关键字参数的版本(您可以根据需要修改它,只需始终以相同的顺序考虑关键字参数...)。没有很重的功能就不要用!
def fk_processed (fk):
filename = fk.__name__ + '_output.json'
def new_fk (*args):
store = {}
if (os.path.exists(filename)):
store = json.load (open(filename))
cstore = store
i = 0
while i < len(args) and str(args[i]) in cstore:
cstore = cstore[str(args[i])]
i += 1
if i != len(args):
while i < len(args) - 1:
cstore[str(args[i])] = {}
cstore = cstore[str(args[i])]
i += 1
# print('compute')
cstore[str(args[i])] = fk (*args)
cstore = cstore[str(args[i])]
json.dump (store, open(filename, 'w'))
return cstore
return new_fk
请注意,我正在将 store
字典中的参数转换为字符串,因为 JSON 只允许字符串作为键。如果您的函数参数不简单,这可能会破坏很多事情。
示例:
>>> @fk_processed
... def add (x, y): return x + y
...
>>> add (1, 2)
compute
3
>>> add (1, 3)
compute
4
>>> add (1, 2)
3
>>> add ('1', '3') # Here is the problem if you can have various types from your arguments
4 # expected '13'