Pythonic使用迭代和条件

时间:2017-09-13 06:21:18

标签: python iteration conditional

这是一个稍微普遍的问题 - 我正在寻找最具蟒蛇味和/或效率的方法:

我有一个大型数据集和一些有时需要通过遍历行执行的任务,有时候根本不需要,具体取决于某些条件。

for step in np.arange (0, number_of_steps):
    if condition1:
        do_calculation1(step)
    if condition2:
        do_calculation2(step)

因此,每次迭代都会重复if个语句。整个数据集的条件为真或假,所以为了节省时间,如果不需要,我不会进行迭代:

if condition1 or condition2:
    for step in np.arange (0, number_of_steps):
            if condition1:
                do_calculation1(step)
            if condition2:
                do_calculation2(step)

但我有时会不必要地重复if次陈述。 另一种方法是分离条件语句,并在数据集中进行两次迭代:

if condition1 :
    for step in np.arange (0, number_of_steps):
        do_calculation1(step)
if condition2:
    for step in np.arange (0, number_of_steps):
        do_calculation2(step)

这样做的缺点是,如果两个条件都为真,我会迭代两次,这很慢(而且很笨拙)。两种方法的相对速度将取决于每种条件的真实频率,但我将使用各种各样的数据,因此我不知道哪种更快。

所以我的问题是哪种方法是最具有pythonic和最有效的方法?

4 个答案:

答案 0 :(得分:3)

这就是我要做的事情:

calculations = [
    f for c,f in [
        (condition1, do_calculation1),
        (condition2, do_calculation2),
    ] if c
]
if calculations:
    for step in np.arange (0, number_of_steps):
        for calc in calculations:
            calc(step)

答案 1 :(得分:1)

您可以简单地结合两种方法:

if not condition1 and not condition2:
    pass
elif not condition1 and condition2
    for step in np.arange (0, number_of_steps):
        do_calculation1(step)
elif condition1 and not condition2:
    for step in np.arange (0, number_of_steps):
        do_calculation2(step)
else: # condition 1 and condition2:
    for step in np.arange (0, number_of_steps):
        do_calculation1(step)
        do_calculation2(step)

我想这更像是一个效率问题,而不是更多的pythonic。

我想这会更加pythonic:

def run_calcs(number_of_steps, *funcs):
    for step in range(number_of_steps):
        for func in funcs:
            func(step)

def gen_func_list(condition1=False, condition2=False):
    func_list = []
    if condition1:
        func_list.append(do_calculation1)
    if condition2:
        func_list.append(do_calculation2)
    return func_list

if __name__ == '__main__':

    number_of_steps = 10

    run_calcs(
        number_of_steps,
        *gen_func_list(
            condition1=<your condition here>,
            condition2=<your condition here>
        )
    )

我认为这也非常易读,适合多处理:

from multiprocessing import Process

def run_calcs(number_of_steps, *funcs):
    for step in range(number_of_steps):
        for func in funcs:
            func(step)

def gen_func_list(condition1=True, condition2=True):
    func_list = []
    if condition1:
        func_list.append(do_calculation1)
    if condition2:
        func_list.append(do_calculation2)
    return func_list

if __name__ == '__main__':

    number_of_steps = 10

    funcs = gen_func_list(
            condition1=<your condition here>,
            condition2=<your condition here>
    )

    proc_handles = []
    for f in funcs:
        proc_handles.append(
            Process(target=run_calcs,
                    args=[number_of_steps, f])
        )

    for p in proc_handles:
        p.start()

    for p in proc_handles:
        p.join()

答案 2 :(得分:0)

我认为第一种是更加pythonic的方法。但是如果你真的想在没有条件的情况下跳过迭代,你可以添加一个break语句:

for ... :
    if not any(condition 1, condition2):
        break
    else:
        if condition1:
            ...
        if condition2:
            ...

这将允许您避免第一步的迭代,或检查两个条件是否满足。

(抱歉格式化,从手机输入。)

答案 3 :(得分:0)

我认为第一种方法是最好的,因为您的数据集要么具有条件(1和/或2)。

for step in np.arange (0, number_of_steps):
if condition1:
    do_calculation1(step)
if condition2:
    do_calculation2(step)

如果这两个条件是互斥的,那么你可以用elif替换第二个条件。这将节省一些计算。

for step in np.arange (0, number_of_steps):
if condition1:
    do_calculation1(step)
elif condition2:
    do_calculation2(step)