← Назад к вопросам

Какие знаешь инструменты оптимизации Python кода?

1.7 Middle🔥 211 комментариев
#REST API и HTTP

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Инструменты оптимизации Python кода

Оптимизация — это процесс выявления узких мест и ускорения критичного кода. Вот практические инструменты которые я использую.

1. Profiling с cProfile

Выявляет какие функции занимают больше всего времени:

import cProfile
import pstats

def slow_function():
    result = 0
    for i in range(1000000):
        result += i ** 2
    return result

# Профилирование
profiler = cProfile.Profile()
profiler.enable()
slow_function()
profiler.disable()

# Вывод результатов
stats = pstats.Stats(profiler)
stats.sort_stats('cumulative')
stats.print_stats()

Вывод:

   ncalls  tottime  percall  cumtime  percall filename:lineno
        1   0.150    0.150    0.150    0.150 script.py:3

2. Line Profiler (line_profiler)

Профилирует каждую строку кода:

pip install line_profiler
# script.py
from line_profiler import profile

@profile
def function_to_optimize():
    result = 0  # Строка 1
    for i in range(1000000):  # Строка 2
        result += i ** 2  # Строка 3
    return result  # Строка 4

function_to_optimize()
kernprof -l -v script.py

Вывод:

Line #      Hits         Time  Per Hit   % Time  Line Contents
    4                                           def function_to_optimize():
    5         1        100.0    100.0    50.0      result = 0
    6   1000001       200.0      0.0    50.0      for i in range(1000000):
    7   1000000       300.0      0.0   100.0          result += i ** 2

3. Memory Profiler (memory_profiler)

Выявляет утечки памяти:

pip install memory_profiler
from memory_profiler import profile

@profile
def create_list():
    x = [i for i in range(1000000)]  # Много памяти
    return x

create_list()
python -m memory_profiler script.py

4. Timing с timeit

Для быстрого сравнения альтернатив:

import timeit

# Способ 1: list comprehension
code1 = '[i*2 for i in range(1000)]'

# Способ 2: map
code2 = 'list(map(lambda i: i*2, range(1000)))'

time1 = timeit.timeit(code1, number=10000)
time2 = timeit.timeit(code2, number=10000)

print(f"List comprehension: {time1:.4f}s")
print(f"Map: {time2:.4f}s")
print(f"Speedup: {time2/time1:.2f}x")

5. Cython для критичного кода

Переводит Python в C для ускорения:

# fib.pyx (Cython)
def fibonacci(int n):
    cdef int a, b
    a, b = 0, 1
    for _ in range(n):
        a, b = b, a + b
    return a
pip install cython
cythonize -i fib.pyx
python -c "from fib import fibonacci; print(fibonacci(100))"

Результат: 1000x быстрее!

6. NumPy для работы с данными

Для массивов NumPy на 100x быстрее чем Python:

import numpy as np

# ПЛОХО: Python loop
result = 0
for i in range(1000000):
    result += i ** 2

# ХОРОШО: NumPy (моментально)
result = np.arange(1000000) ** 2
result = result.sum()

7. Numba для JIT компиляции

Автоматическая компиляция в машинный код:

from numba import jit

@jit(nopython=True)  # JIT компиляция
def sum_of_squares(n):
    result = 0
    for i in range(n):
        result += i ** 2
    return result

sum_of_squares(1000000)  # Работает как C

8. Database Query Optimization

# ПЛОХО: N+1 query
users = User.objects.all()
for user in users:  # 1 запрос
    print(user.profile.age)  # N запросов

# ХОРОШО: JOIN через select_related
users = User.objects.select_related('profile').all()
for user in users:  # 1 запрос вместо N+1
    print(user.profile.age)

9. Caching стратегии

from functools import lru_cache

# LRU Cache для функций
@lru_cache(maxsize=128)
def expensive_calculation(n):
    return sum(i ** 2 for i in range(n))

expensive_calculation(1000)  # Вычисляет
expensive_calculation(1000)  # Использует кеш

# Redis для распределённого кеша
import redis

client = redis.Redis()

def cached_db_query(user_id):
    # Проверяем кеш
    cached = client.get(f'user:{user_id}')
    if cached:
        return json.loads(cached)
    
    # Запрашиваем БД
    user = User.objects.get(id=user_id)
    
    # Кешируем на 1 час
    client.setex(
        f'user:{user_id}',
        3600,
        json.dumps(user.to_dict())
    )
    return user.to_dict()

10. Lazy Loading и Generators

Обработка больших датасетов без загрузки в память:

# ПЛОХО: загружает всё в память
def read_file(filename):
    with open(filename) as f:
        return f.readlines()  # Весь файл в памяти!

# ХОРОШО: generator (на лету)
def read_file(filename):
    with open(filename) as f:
        for line in f:
            yield line.strip()  # По строке за раз

# Использование
for line in read_file('huge_file.txt'):
    process(line)

11. Асинхронность с asyncio

Параллельная обработка I/O операций:

import asyncio
import aiohttp

# ПЛОХО: синхронные запросы
for url in urls:
    response = requests.get(url)  # Ждём каждый запрос
    process(response)

# ХОРОШО: асинхронные запросы
async def fetch_all(urls):
    async with aiohttp.ClientSession() as session:
        tasks = [fetch_url(session, url) for url in urls]
        return await asyncio.gather(*tasks)

async def fetch_url(session, url):
    async with session.get(url) as response:
        return await response.json()

asyncio.run(fetch_all(urls))

12. Compilation и Optimization Flags

# Optimize imports
python -O script.py  # Удаляет assert и __debug__

# Compile to bytecode
python -m compileall .

# PyPy для быстрого выполнения
pip install pypy3
pypy3 script.py  # Может быть 5-10x быстрее!

13. Algoritm Optimization

Лучший алгоритм > любая оптимизация:

# ПЛОХО: O(n²)
def find_duplicates(numbers):
    for i in range(len(numbers)):
        for j in range(i + 1, len(numbers)):
            if numbers[i] == numbers[j]:
                return True
    return False

# ХОРОШО: O(n)
def find_duplicates(numbers):
    seen = set()
    for num in numbers:
        if num in seen:
            return True
        seen.add(num)
    return False

Чеклист оптимизации

Шаг 1: Profiling

  • Запусти cProfile на production данных
  • Выявь Top-5 медленных функций
  • Используй memory_profiler для утечек

Шаг 2: Database

  • Используй select_related/prefetch_related
  • Добавь индексы
  • Кешируй часто запрашиваемые данные

Шаг 3: Algorithm

  • Проверь сложность O(n)
  • Используй правильные структуры данных
  • Избегай loop inside loop

Шаг 4: Code

  • Используй list comprehension вместо loops
  • Кешируй функции (lru_cache)
  • Используй generators для больших датасетов

Шаг 5: Deployment

  • Используй PyPy если возможно
  • Кешируй с Redis
  • Используй CDN для статики
  • Используй async для I/O операций

Правило: профилируй перед оптимизацией, не угадывай!