【问题标题】:Pythonic use of iterations and conditionalsPythonic 使用迭代和条件
【发布时间】:2018-02-21 17:30:54
【问题描述】:

这是一个稍微笼统的问题 - 我正在寻找最pythonic和/或最有效的方法:

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

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 和最有效的方法?

【问题讨论】:

    标签: python iteration conditional


    【解决方案1】:

    这就是我会做的:

    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)
    

    【讨论】:

    • 喜欢这个——pythonic 和高效。
    【解决方案2】:

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

    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)
    

    我想这更多的是效率问题,而不是更 Python 的问题。

    我想这会更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()
    

    【讨论】:

    • 谢谢。是的,这样更有效率。我想我正在寻找效率 pythonicity(?)。
    • @doctorer 谢谢,现在它更像 Python 了,性能也更好了。
    【解决方案3】:

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

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

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

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

    【讨论】:

      【解决方案4】:

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

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

      如果两个条件互斥,则可以将第二个 if 替换为 elif。这将节省一些计算。

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-08-18
        • 1970-01-01
        • 2018-11-28
        • 2022-01-02
        • 1970-01-01
        相关资源
        最近更新 更多