3

Taking this code, for example, can you explain why using a list comprehension when adding sum of integers in list took longer than using a normal for loop?

class Store:
    def __init__(self, name):
        self.name = name
        self.items = []

    def add_items(self, name, price):
        self.items.append({'name':name, 'price': price})

    def stock_price(self):
        return sum([item['price'] for item in self.items])

    def stock_price2(self):
        total = 0
        for item in self.items:
            total += item.get('price')
        return total

store = Store("Jay")
store.add_items("nike", 100)
store.add_items('puma', 200)
print(timeit.Timer(lambda: store.stock_price()).timeit(number=1000))
print(timeit.Timer(lambda: store.stock_price2()).timeit(number=1000))

result of stock_price: 0.0007737720006844029

result of stock_price2: 0.0006722800026182085

jonrsharpe
  • 115,751
  • 26
  • 228
  • 437
jsonp
  • 31
  • 1
  • 6
    The list comprehension version builds a new list then invokes a function call; if you don't actually *need* the new list, it seems inevitable that a simpler loop will be faster. – jonrsharpe Jun 25 '18 at 16:35
  • 2
    Try that but with a list which doesn't have just one item (but say a thousand items) and post the results. I bet the list comprehension will be faster – kosnik Jun 25 '18 at 16:39
  • Thanks to @jonrsharpe: the approach with summing the generator is not really faster than list comprehension. The explanation can be found here: https://stackoverflow.com/a/11964478/747744 (TLDR: generators can be slow because of extra calls to ```next()```) – Eugene Primako Jun 25 '18 at 17:05

2 Answers2

1

In the first function, there is an extra step. It first creates a list, then sums it all together with sum. The second function simply iterates over them and adds it to a total.

sam-pyt
  • 1,027
  • 15
  • 26
  • In fact the extra step in first function doesn't make it slower: https://stackoverflow.com/a/11964478/747744 (I've rechecked it on 10 million items) – Eugene Primako Jun 25 '18 at 17:07
0

As jonrsharpe suggested, list comrehension makes a copy of the list. So what stock_price() does is actually make a copy of the list, and only then iterating on it and calculating the sum. (note that the builtin sum function is actually more efficient than a for look, as it is implemented in C)

On the other hand, stock_price2() does not copy the list, which saves a lot of time spent on allocations for the new list.

Elro444
  • 136
  • 7