Сужаем зону поиска
деление пополам вместо чтения всего подряд
Что это
Когда непонятно, где ошибка, читать весь код подряд — худший способ её найти. Есть приём надёжнее: разделить путь данных пополам, проверить середину и выбросить ту половину, где всё хорошо.
Так зона поиска сокращается вдвое на каждом шаге. Из тысячи строк до нужной — десять проверок.
Как выглядит в коде
На живом примере
Цепочка из четырёх функций: загрузить строки, разобрать, превратить в числа, посчитать среднее. Падает где-то внутри.
def load_rows(raw: str) -> list[str]: ...
def parse_rows(rows: list[str]) -> list[dict]: ...
def to_numbers(items: list[dict]) -> list[dict]: ...
def average(items: list[dict]) -> float: ...
print(average(to_numbers(parse_rows(load_rows(RAW)))))Шаг 1. Печатаем в середине. Не в начале и не в конце — ровно посередине цепочки:
rows = load_rows(RAW)
items = parse_rows(rows)
print("после parse_rows:", items)после parse_rows: [{'city': 'Oslo', 'temp': '4'},
{'city': 'Bergen', 'temp': '7'},
{'city': 'Tromso', 'temp': '-2.5'}]Данные в порядке. Значит, первая половина цепочки чистая, и её можно забыть. Осталось две функции из четырёх.
Шаг 2. Делим остаток. Проверяем to_numbers на тех же данных, по
элементам:
for it in items:
try:
int(it["temp"])
except ValueError as e:
print("падает на:", it, "->", e)падает на: {'city': 'Tromso', 'temp': '-2.5'} -> invalid literal for int() with base 10: '-2.5'Две проверки — и найдены и строка, и конкретные данные. Причина видна сразу: код предполагал целые температуры, а в данных дробная.
Где делить
| Что ищем | Где середина |
|---|---|
| Ошибка в цепочке функций | между функциями, по данным |
| Ошибка в длинной функции | между логическими блоками |
| Ошибка появилась после правок | git log — между коммитами |
| Ошибка на одном из тысячи элементов | по половине списка |
Третья строка — отдельный приём: если код работал вчера и сломался сегодня,
делить надо не код, а историю коммитов. У git для этого есть git bisect,
но часто хватает и ручного переключения на коммит из середины.
Как сказать ИИ
Вот цепочка из четырёх функций, где-то внутри падает.
Куда поставить одну печать, чтобы разделить цепочку пополам?
Код не чини, скажи только место.Я напечатал данные после parse_rows, они в порядке.
Значит, ошибка дальше. Что проверить следующим?Такой диалог экономит время: ИИ хорошо подсказывает, где середина, а выполняешь и смотришь ты.
На что смотреть
Печать в начале и в конце вместо середины. Начало обычно в порядке, конец обычно сломан — обе проверки не сужают зону.
ИИ предлагает чинить, не сузив зону. Типичный ответ на «не работает» — три гипотезы сразу. Любая может быть верной, проверять придётся все. Сузь сам, потом проси починку.
Зона не сужается, а растёт. Если после каждой проверки появляются новые подозреваемые, значит, проверяются следствия, а не данные. Вернись к вопросу «данные здесь ещё целые?».
Отладка без записи. Проверил три места, забыл результаты, проверяешь заново. Записывай по строке: «после parse_rows — нормально».
Шпаргалка
Дели путь данных пополам, проверяй середину, выбрасывай чистую половину.
Вопрос на каждом шаге: «данные здесь ещё целые?»
Из тысячи строк до одной — десять проверок.
Сломалось после правок — дели историю коммитов, не код.
Печать в начале и в конце зону не сужает.
Записывай результаты проверок, иначе будешь ходить по кругу.