Главное правило: «сначала угадай — потом замерь»
Если вы запомните из этого вступления только одно — пусть это будет это правило. В каждом уроке, когда вы видите бенчмарк или вопрос «что будет быстрее: A или B» — остановитесь и угадайте сами, прежде чем смотреть ответ. Запишите цифру или вариант. Только потом запустите код.
Почему это важно: мозг учится не на пассивном чтении, а на исправлении предсказаний. Когда вы угадали, и совпало — закрепили интуицию. Когда не угадали — выяснили, где ваша модель сломана, и это запомнилось. Если просто читаете «А быстрее B в 100 раз» — через два дня забудете. Если угадали 10 раз и три раза ошиблись — будете помнить именно те три случая. И в этом ценность.
Этот цикл — единственный способ превратить чтение в навык. Все остальные подходы тратят ваше время.
Запускайте каждый код
Это второе правило, не менее важное. Когда видите code-блок в уроке — не читайте его как текст. Откройте редактор, скопируйте, запустите, посмотрите вывод.
«Ну я же программист, я по коду в голове его выполню» — нет. Вы получите 70% правильно, и именно те 30%, в которых вы ошибаетесь, и есть то, ради чего вы пришли учиться. Если бы вы могли всё в голове выполнить без ошибок — DSA вам уже не нужен.
Конкретный workflow:
mkdir -p ~/projects/dsa-course/m02 # модуль 3
cd ~/projects/dsa-course/m02
touch lesson_01_memory_hierarchy.py # под каждый урок отдельный файл
Дальше копируете код из урока в файл и запускаете:
python lesson_01_memory_hierarchy.py
Так у вас остаётся личная коллекция бенчмарков — после курса можно вернуться, перезапустить и сравнить с цифрами в уроке.
timeit правильно
Главный инструмент измерений — timeit. Но им можно пользоваться правильно и неправильно. Правильно:
import timeit
# 1) setup — отдельно, чтобы не входил в замер
# 2) stmt — то, что мерим
# 3) number — сколько раз повторить (для стабильности)
# 4) repeat — сколько раз повторить весь блок (для min/median)
t = timeit.repeat(
stmt='lst.append(0)',
setup='lst = []',
number=10_000,
repeat=5,
)
print(f"min: {min(t):.4f}s, median: {sorted(t)[2]:.4f}s")
Что важно:
- Берём
min, а неmean. Среднее искажается случайными скачками CPU (например, фоновые процессы). Минимум — это «лучшее, что машина смогла», и оно стабильнее. numberрегулирует точность одного замера. Если вашstmtсам по себе занимает 0.1ns, нужноnumber=1_000_000, чтобы получить измеримое время. Еслиstmtуже 1 секунду —number=1достаточно.repeatрегулирует надёжность. 5-7 повторов хватает в большинстве случаев.
Современные ноутбуки на батарее снижают частоту CPU, и timeit показывает дикие разбросы. Воткните зарядку и закройте Chrome с 200 вкладками. Иначе ваши цифры будут шуметь в разы.
Простой helper
Чтобы не писать setup/number/repeat каждый раз, заведите helper:
# bench.py — положите в каждый рабочий каталог
import timeit
def bench(stmt: str, setup: str = "", n: int = 10_000, repeat: int = 5) -> float:
"""Возвращает min time в секундах за один вызов stmt."""
times = timeit.repeat(stmt, setup=setup, number=n, repeat=repeat)
return min(times) / n # время на одну операцию
# использование:
t = bench('lst.append(0)', setup='lst = []')
print(f"list.append: {t * 1e9:.1f} ns")
Этот helper будет полезен на всём протяжении курса.
Не пропускайте «Попробуй сам»
В каждом уроке есть блок «Попробуй сам» — это не дополнительное упражнение для отличников, это основной механизм закрепления. Пропустить блок «Попробуй сам» — то же самое, что читать руководство по плаванию без воды.
Запустите этот код. Угадайте перед запуском, какое число будет в первой строчке вывода (диапазон в наносекундах).
import timeit
t_list = min(timeit.repeat('1 in lst', setup='lst = list(range(1000))', number=100_000, repeat=5))
t_set = min(timeit.repeat('1 in s', setup='s = set(range(1000))', number=100_000, repeat=5))
print(f"1 in list (1000 items): {t_list * 1e9 / 100_000:.1f} ns")
print(f"1 in set (1000 items): {t_set * 1e9 / 100_000:.1f} ns")Какое отношение времён? 2x? 10x? 100x? Запишите на бумаге, запустите, сверьтесь.
Делайте записи
Третье правило — ведите конспект. Не переписывайте уроки слово в слово, а записывайте:
- Числа, которые вы измерили. Какой
list.appendns на вашей машине, какойdict[key]ns. Через 2 модуля захочется свериться. - Сюрпризы — моменты, где вы угадали неправильно. Это самые ценные записи.
- Свои вопросы — то, что не понятно. После пары уроков половина прояснится, оставшаяся половина — реальные пробелы, которые надо закрыть отдельно.
Формат — любой. Бумажная тетрадь, markdown-файл, Notion — что удобно. Главное — записывать руками или клавиатурой, а не «у меня в голове».
Если вы застряли
Курс плотный. На каком-то уроке может стать непонятно. Что делать:
Не паникуйте, не бросайте курс. Пройдите по шагам.
90% «я застрял» лечится первыми тремя шагами. Если дошли до пятого — это уже не «застрял», а реальный пробел, который стоит обсудить.
Темп и расписание
Курс на ~60 часов. Это:
- 3 урока в неделю по 20 минут — растянется на ~5 месяцев, но усвоится глубоко.
- 5 уроков в неделю по 30 минут — ~3 месяца, оптимальный темп для работающих.
- Спринт 2-3 часа в день — ~1 месяц, но без практики материал утечёт. Не рекомендую.
Каждое утро (или вечер — как удобно) по одному уроку — намного эффективнее, чем «по 5 часов в субботу». Память консолидируется во сне, а не за один присест.
Если вы прочитали этот урок, у вас на машине:
- Стоит Python 3.13.
- Есть каталог
~/projects/dsa-course/(или аналогичный). - Лежит файл
bench.pyс helper-функцией из этого урока. - Понятно правило «сначала угадай — потом замерь».
Если всё да — поздравляю, фундамент готов. Переходим к Big-O.
В следующем модуле — что такое Big-O, какие классы сложности существуют и почему джунам важно знать константы тоже.