Как ускорить Python-код: 12 маленьких приёмов, которые реально работают

Кратко: Эти 12 простых приёмов ускорят ваш Python-код — без сложных библиотек, только стандартные возможности и правильный подход.
Как ускорить Python-код

Многие почему то считают Python «медленным» языком — и часто сами делают код ещё медленнее, не зная тонкостей. При этом правильно написанный Python может быть в разы быстрее «грязного», даже без Cython или Numba.

В этой статье — 12 проверенных приёмов, которые реально ускоряют код:

  • от выбора структур данных,
  • до профилирования и кэширования.

Все примеры — с замерами времени, пояснениями и готовым кодом.

1. Используйте set вместо list для проверки вхождения

Проблема

items = list(range(10000))
if 9999 in items:  # O(n) — линейный поиск
    ...

Это очень медленно при больших списках.

Решение

items = set(range(10000))
if 9999 in items:  # O(1) — мгновенно
    ...

💡 set использует хеш-таблицу — проверка принадлежности — константная.

2. Собирайте строки через str.join(), а не +=

Медленный способ

result = ""
for word in words:
    result += word + " "  # создаёт новый объект каждый раз

Быстрый способ

result = " ".join(words)  # один вызов, минимум аллокаций

📊 На 10 000 строк разница — в 100 раз.

3. List comprehensions быстрее циклов for

Сравнение

# Медленно
squares = []
for x in range(1000):
    squares.append(x**2)

# Быстро
squares = [x**2 for x in range(1000)]

List comprehension компилируется в более эффективный байт-код. Подробнее о list comprehensions и других python фишках — в статье редкие трюки python.

4. Используйте collections.Counter вместо ручного подсчёта

Плохо

counts = {}
for item in items:
    counts[item] = counts.get(item, 0) + 1

Хорошо

from collections import Counter
counts = Counter(items)

И быстрее, и читабельнее.

📚 Документация: collections.Counter

5. Кэшируйте дорогие вызовы через @lru_cache

from functools import lru_cache

@lru_cache(maxsize=128)
def expensive_function(n):
    return fib(n)  # рекурсивный подсчёт

print(expensive_function(40))  # повторный вызов — мгновенно

💡 Идеально для рекурсии, API-запросов, сложных вычислений.

Кэширование особенно полезно в скриптах, которые запускаются регулярно — например, в автоматическом резервном копировании файлов, где повторные вызовы одних и тех же функций неизбежны.

6. Профилируйте код — не гадайте

Не оптимизируйте наугад. Используйте встроенный профилировщик:

import cProfile

def main():
    # ваш код
    pass

cProfile.run('main()', sort='cumtime')

Он покажет, какие функции тратят больше всего времени.

7. Избегайте повторных вычислений в цикле

Ошибка

for i in range(len(data)):
    process(data[i], config.get("param"))  # вызывается на каждой итерации

Исправление

param = config.get("param")
for item in data:
    process(item, param)

8. Выбирайте правильные структуры данных

  • Нужно быстро добавлять в конец и удалять с начала? → collections.deque
  • Нужен очередь по приоритету? → heapq
  • Нужны именованные поля? → dataclass или namedtuple

Пример:

from collections import deque
q = deque()
q.appendleft(1)  # O(1)
q.pop()          # O(1)

9. Не копируйте данные без необходимости

Используйте срезы, генераторы, itertools:

# Вместо
big_list[:] = [x for x in big_list if x > 0]

# Лучше — фильтр «на лету»
filtered = (x for x in big_list if x > 0)

Генераторы экономят память и время.

10. Используйте f-строки вместо .format() и %

name = "Иван"
# Быстро
msg = f"Привет, {name}!"
# Медленно
msg = "Привет, {}!".format(name)

F-строки компилируются на этапе парсинга — это самый быстрый способ.

11. Избегайте глубокой вложенности в циклах

Если внутри цикла — ещё цикл — и ещё один — код не только медленный, но и не читаемый. Выносите логику в функции:

for user in users:
    if is_active(user):
        send_report(user)  # внутри — своя проверка данных

12. Замеряйте — не верьте на слово

Используйте timeit для точных замеров:

import timeit

time1 = timeit.timeit(lambda: " ".join(words), number=10000)
time2 = timeit.timeit(lambda: slow_concat(words), number=10000)
print(f"join быстрее в {time2/time1:.1f} раз")

Заключение

Ускорение Python — это не про магию, а про осознанный выбор:

  • Правильные структуры данных
  • Минимизация операций
  • Кэширование и профилирование

Эти 12 приёмов работают сегодня, без установки новых библиотек, и особенно полезны, когда вы пишете автоматизированные скрипты — будь то парсинг, бэкапы или уведомления. Чтобы глубже освоить эти навыки, изучите рубрику Советы и Python-трюки.

🐍 Помните: лучшая оптимизация — не делать лишнего.

🧠 Если вам полезны советы по Python, посмотрите также:
чистый код python — как писать понятные и поддерживаемые скрипты
редкие трюки python — малоизвестные, но мощные фичи языка
💬 Остались вопросы? Пишите в комментариях — с радостью уточню, дополню или помогу с вашим кодом.
📢 Подписывайтесь на Telegram-канал PythonAuto, чтобы не пропустить новые гайды по автоматизации, парсингу и Python.
👉 Ваш интерес — лучшая мотивация для новых статей!

Оставьте комментарий