Search code examples
pythonif-statementlist-comprehension

Why "if condition" in two list comprehantions work faster then one cycle for with 2 two conditions?


import time
from random import random
from typing import List


def test(arr: List[int] | None = None) -> None:
    if not arr:
        raise TypeError("Variable arr must exist!")
    
    opp = arr.pop()

    def check_time(func, msg):
        t0 = time.perf_counter()
        func()
        print(f"{msg}\ntime - {time.perf_counter() - t0}")

    def first_method():
        more_arr = [e for e in arr if e > opp]
        less_arr = [e for e in arr if e < opp]
        return less_arr, more_arr

    def second_method():
        more_arr, less_arr = [], []
        for e in arr:
            if e > opp:
                more_arr.append(e)
            elif e < opp:
                less_arr.append(e)
        return less_arr, more_arr

    check_time(first_method, "first_method")
    check_time(second_method, "second_method")
    """
    [RESULT]
    first_method
    time - 0.1035286999976961
    second_method
    time - 0.12783881399809616
    """


def main() -> None:
    test([int(random() * 1000) for _ in range(1_000_000)])


if __name__ == '__main__':
    main()

RESULT:

first_method: time - 0.10790603799978271

second_method: time - 0.1264369229975273

-------------------------------------------------------------

I wont to know why first_method() faster then second_method()?

How work "if" condition in list_comprehension from the point of view of optimization?


Solution

  • Add this third method to see that the retrieving of the append methods needs a lot of time:

        def third_method():
            more_arr, less_arr = [], []
            m = more_arr.append
            l = less_arr.append
            
            for e in arr:
                if e > opp:
                    m(e)
                elif e < opp:
                    l(e)
            return less_arr, more_arr
    

    This method is usually even slightly faster than the first one.