0

I have this two versions to sum of elements in a list. But i ignore what is the reason for, the second version its faster than first.

What it happening under the hood?

import time

def add(x, y):
    time.sleep(1)
    return x + y

values = [1, 2, 3, 4, 5, 6, 7, 8]
start_time = time.time()
while len(values) > 1:
    values = [add(values[0], values[1])] + values[2:]
    print(values)
result = values[0]
print(result, time.time()-start_time)

start_time = time.time()
while len(values) > 1:
    values = values[2:] + [add(values[0], values[1])]
    print(values)
result = values[0]
print(result, time.time()-start_time)
eyllanesc
  • 235,170
  • 19
  • 170
  • 241
William Trigos
  • 360
  • 1
  • 10

1 Answers1

1

The reason method 2 is "faster" is because the values list is not reinstantiated after method 1 runs, so when method 2 runs, len(values) is 1, so nothing happens.

If you reinstantiate, the two methods will take approximately the same amount of time:

import time

def add(x, y):
    time.sleep(1)
    return x + y

values = [1, 2, 3, 4, 5, 6, 7, 8]

start_time = time.time()
while len(values) > 1:
    values = [add(values[0], values[1])] + values[2:]
    print(values)
result = values[0]
print(result, time.time()-start_time)

values = [1, 2, 3, 4, 5, 6, 7, 8]

start_time = time.time()
while len(values) > 1:
    values = values[2:] + [add(values[0], values[1])]
    print(values)
result = values[0]
print(result, time.time()-start_time)
[3, 3, 4, 5, 6, 7, 8]
[6, 4, 5, 6, 7, 8]
[10, 5, 6, 7, 8]
[15, 6, 7, 8]
[21, 7, 8]
[28, 8]
[36]
36 7.014946937561035
[3, 4, 5, 6, 7, 8, 3]
[5, 6, 7, 8, 3, 7]
[7, 8, 3, 7, 11]
[3, 7, 11, 15]
[11, 15, 10]
[10, 26]
[36]
36 7.015171766281128

If you remove time.sleep(1) and just add the two numbers natively, you will see that method #2 does appear to be faster:

import time

values = [1, 2, 3, 4, 5, 6, 7, 8]

start_time = time.time()
while len(values) > 1:
    values = [values[0] + values[1]] + values[2:]
    print(values)
result = values[0]
print(result, time.time()-start_time)

values = [1, 2, 3, 4, 5, 6, 7, 8]

start_time = time.time()
while len(values) > 1:
    values = values[2:] + [values[0] + values[1]]
    print(values)
result = values[0]
print(result, time.time()-start_time)
[3, 3, 4, 5, 6, 7, 8]
[6, 4, 5, 6, 7, 8]
[10, 5, 6, 7, 8]
[15, 6, 7, 8]
[21, 7, 8]
[28, 8]
[36]
36 7.319450378417969e-05
[3, 4, 5, 6, 7, 8, 3]
[5, 6, 7, 8, 3, 7]
[7, 8, 3, 7, 11]
[3, 7, 11, 15]
[11, 15, 10]
[10, 26]
[36]
36 2.7894973754882812e-05

However, if you wrap the core logic of the two methods in functions and run them multiple times, with a larger list, you can see that their runtime is basically the same:

import time

def method1(values):
    start_time = time.time()
    while len(values) > 1:
        values = [values[0] + values[1]] + values[2:]
    return time.time()-start_time

def method2(values):
    start_time = time.time()
    while len(values) > 1:
        values = values[2:] + [values[0] + values[1]]
    return time.time()-start_time


vals = list(range(1000))

average_1 = sum(method1(vals[:]) for _ in range(100))/100
average_2 = sum(method2(vals[:]) for _ in range(100))/100

print(average_1)
print(average_2)
0.0029142618179321287
0.0029442691802978515
Angus L'Herrou
  • 429
  • 3
  • 11