pythonic方式重用样板循环结构而不调用if子句n次

问题描述 投票:2回答:2

我继承了一个遗留代码库,其中包含许多嵌套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专家所以我可能会忽略一些方便的高级功能,这些功能在这里很有用。

任何建议都非常感谢。

python
2个回答
5
投票

理想情况下,您将传递函数本身而不是状态变量,但由于这是遗留代码,因此无需更改界面即可设置一个函数字典,如下所示:

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)

3
投票

如果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)

© www.soinside.com 2019 - 2024. All rights reserved.