我继承了一个遗留代码库,其中包含许多嵌套for循环,如下所示:
def func(infile, some_other_data, outfile, status_variable):
with open(infile, 'r') as f:
with open(outfile, 'w') as outf:
for line in f:
# parse line
for element in some_other_data:
standard_function(line, element)
if status_variable == 'status_A':
function_A(line, element)
elif status_variable == 'status_B':
function_B(line, element)
# handle other possible status variables
outf.write(new_line)
此代码与性能相关。为了加快速度(除了其他变化),我想摆脱所有被称为n * m次的if子句,测试表明这确实提高了10%。
为此,我只是为每个可能的状态变量复制并修改了主循环函数,并相应地调用了不同的函数。这有效地将if子句移到了循环之外。然而,它非常难看,并使图书馆4倍大。
是否有一种(相当)简单的pythonic方式处理这种情况,我想重用样板循环,只是改变每次迭代所做的事情,而不是每次处理条件?
我一直在玩装饰器动态返回循环函数,根据状态变量调用不同的子函数,但从可读性的角度看,最终结果看起来很糟糕。我绝不是一个python专家所以我可能会忽略一些方便的高级功能,这些功能在这里很有用。
任何建议都非常感谢。
理想情况下,您将传递函数本身而不是状态变量,但由于这是遗留代码,因此无需更改界面即可设置一个函数字典,如下所示:
def func(infile, some_other_data, outfile, status_variable,
status_functions={
'status_A': function_A,
'status_B': function_B,
}
):
try:
status_function = status_functions[status_variable]
except KeyError:
status_function = lambda line, element: None
with open(infile, 'r') as f, open(outfile, 'w') as outf:
for line in f:
# parse line
for element in some_other_data:
standard_function(line, element)
status_function(line, element)
# handle other possible status variables
outf.write(new_line)
如果status_variable
- > function_name之间存在直接对应关系,并且所有调用都是常规的:function(line, element)
,您可以传入函数:
def func(infile, some_other_data, outfile, function_from_status_variable):
with open(infile, 'r') as f:
with open(outfile, 'w') as outf:
for line in f:
# parse line
for element in some_other_data:
standard_function(line, element)
function_from_status_variable(line, element)
outf.write(new_line)
这是计算一次,因此:
def calc_function(status_variable):
if status_variable == 'status_A':
return function_A
elif status_variable == 'status_B':
return function_B
# other tests follow, plus handle an unknown value
最后调用这样的函数:
function = calc_function(status_variable)
func(infile, some_other_data, outfile, function)