Skip to main content

Command Palette

Search for a command to run...

Python comprehensions vs cycles

Published
2 min read
A

Backend developer, team leader.

Almost all python programmers know that there are list comprehensions PEP 202.

# create list of odd numbers with cycle
a = []
for i in range(10):
    if i % 2:
        a.append(i)

# create same collection using list comprehension
a = [i for i in range(10) if i % 2]

It isn’t only syntax sugar, comprehensions have CPython code optimisations and work faster. But what benefits do they provide? Let’s try to evaluate this.

I wrote a simple python program to compare execution for operation create collections using cycles and comprehensions. We will check dict, list and set. Base class for benchmarking has methods

from typing import Dict, List, Set

class BaseBench:

    def __init__(self, n: int = 1) -> None:
        self.n = n

    def get_new_dict(self) -> Dict[int, str]:
        raise NotImplementedError

    def get_filtered_dict(self, data: Dict[int, str]) -> Dict[int, str]:
        raise NotImplementedError

    def get_new_set(self) -> Set[int]:
        raise NotImplementedError

    def get_filtered_set(self, data: Set[int]) -> Set[int]:
        raise NotImplementedError

    def get_new_list(self) -> List[int]:
        raise NotImplementedError

    def get_filtered_list(self, data: List[int]) -> List[int]:
        raise NotImplementedError

I write here a part of code, example only for dict. Other listings you can find in github:

class CycleBench(BaseBench):

    def get_new_dict(self) -> Dict[int, str]:
        result = {}
        for i in range(self.n):
            if i % 2:
                result[i] = 'odd'
            else:
                result[i] = 'even'
        return result

    def get_filtered_dict(self, data: Dict[int, str]) -> Dict[int, str]:
        result = {}
        for key, value in data.items():
            if key % 2:
                result[key] = value
        return result


class ComprehensionBench(BaseBench):

    def get_new_dict(self) -> Dict[int, str]:
        return {i: 'odd' if i % 2 else 'even' for i in range(self.n)}

    def get_filtered_dict(self, data: Dict[int, str]) -> Dict[int, str]:
        return {key: value for key, value in data.items() if key % 2}

It’s interesting to check comprehension efficiency with different sizes of collections, small [10-1000] and big [10k-100k].

comprehension_vs_cycle_small.png

comprehension_vs_cycle_big.png

We see that more efficiency of comprehension is for list, and there is minimal time difference for dict.

Conclusion

Yes, comprehension is faster and often does code more readable. But it is not a rule «always use comprehension». For some cases cycles are better. For example sometimes maintainability may be more important than performance.

More from this blog

Беззнаковые целые числа в программировании

Зачем они нужны? Это небольшой рассказ о беззнаковых целых числах (unsigned integers) в программировании. С математической точки зрения, это немного странная конструкция, зачем вообще нужны какие-то "урезанные" числа? Но всё-таки для этого есть причи...

Jan 9, 202612 min read

Храните деньги в ...

Попытаемся в это посте понять как лучше хранить деньги в базах данных и какой тип использовать для работы с ними в коде. А в чём вообще проблем? Что не так с числами с плавающей точкой? Если кратко, то с ними все хорошо, но только они вообще не про...

Apr 14, 202212 min read
Храните деньги в ...

Классы-итераторы и генераторы в Python

В языке программирования Python есть понятия итераторов и генераторов. Оба термина не очень сложные и часто является обычными вопросами для собеседований разработчиков. Но в данной статье хочется разобрать немного примеров как создавать подобные объе...

Jan 16, 20223 min read

z0rr0's blog

8 posts

Backend developer, tech leader.