Недавно тут на Хабре в блоге издательства БХВ написали пост о книге "Python для инженерных задач", которая недавно вышла. А в этом посте я решил рассказать о той же самой книге с другой стороны баррикады, с точки зрения автора, о том, как появилась идея этой книги, и о том, как шел процесс ее написания.
Как родилась идея книги
Все началось в начале 2024 года, когда мне написал @OlegSivchenko, руководитель проектов в издательстве БХВ. Мы немного пообсуждали уже вышедшие книги, и Олег предложил написать книгу про Python. Надо сказать, что этот разговор случился в очень удачное время - тогда я готовился к двухсеместровому курсу для студентов, в рамках которого я сначала рассказываю основы Python, а потом перехожу к алгоритмам моделирования электродинамических задач (целый семестр рассказываю про метод конечных разностей во временной области - FDTD), а в перспективе у меня маячил еще один двухсеместровый курс, полностью посвященный Python. В момент общения с Олегом я как раз планировал темы для лекций, готовил исходники и презентации. И тогда я подумал, почему бы не согласиться на такое интересное предложение и действительно не оформить материал в виде книги?
Сначала можно было не торопиться, через несколько месяцев у меня сформировался план лекций для студентов, и на его основе я написал первую версию оглавления книги. Мы с Олегом немного его подкорректировали и через несколько итераций утвердили. Я грубо прикинул, сколько страниц займет такой текст. По моим первоначальных подсчетам должно было быть около 500 страниц. Забегая вперед, скажу, что это была очень оптимистическая оценка - в итоге получилось 670 страниц. Руководство издательства согласилось, что такая книга их интересует, окончательно утвердили оглавление, и в конце мая 2024 года я подписал договор с издательством, по которому обещал через год отправить им текст книги. Работа началась, отступать было некуда.
Таким образом сформировались задумка и структура книги. Предполагалось, что основная аудитория будущей книги - это студенты технических вузов, которые уже что-то знают о программировании, по крайней мере им не надо объяснять, что такое переменная и цикл, а самые продвинутые из них может быть даже программировали на C++ или Java, но никогда не работали с Python. Поэтому при объяснении основ языка иногда проскакивают отсылки к другим языкам, а во введении коротко рассказывается об отличиях языков программирования: компилируемые, интерпретируемые и компилируемые в байт-код.
При описании языка Python и его библиотек я держал в голове тот факт, что студенты учатся не на программистов, и Python им нужен не для разработки веб-приложений или низкоуровневых библиотек, а для расчетов. Поэтому, например, в книге ничего не сказано о метаклассах, асинхронщине, о работе сборщика мусора, работе с сетью и т.п. Но зато подробно рассмотрены основные структуры данных: списки, массивы, кортежи, словари, множества, замороженные множества, строки. Строкам посвящены сразу несколько глав: основные операции со строками, способы форматирования строк (с помощью оператора %, метода format() и f-строк), а спустя несколько глав будет глава про регулярные выражения.
После описания основных типов языка я начал писать главы про функции, ООП, обработку исключений, аннотации типов, про модули и установку библиотек, в том числе с использованием виртуальных окружений. Сейчас, наверное, в главе про виртуальные окружения помимо стандартного venv я бы ограничился только инструментом uv, но когда я писал эту главу, uv только набирал популярность, и поэтому сначала в этой главе описан Poetry, а затем uv.
Далее начинается более практическая часть, основная задача которой - дать представление о стандартной библиотеке Python. Сюда можно отнести главы про работу с файловой системой (модули os.path, pathlib, shutil), разбор параметров командной строки с помощью модуля argparse. Сюда же как раз попала глава про регулярные выражения, а заканчивается этот блок главой про тестирование приложений. С этой главой у меня были сложные отношения. С одной стороны я считаю, что нужно знать, как работать со стандартным модулем unittest, чтобы затем перейти на pytest. Но pytest пришлось оставить за бортом, поскольку рассказывать про него без описания фикстур (fixtures) бессмысленно, но тогда перед этим надо рассказывать про генераторы и инструкцию yield, а я этого хотел избежать, учитывая целевую аудиторию книги. Поэтому pytest я только упомянул в заключении этой главы.
И после всего этого начинается третья часть, которая и дала название всей книге. В этой части нужно было рассказать про то, как применять Python для решения инженерных и научных задач. И тут возникла еще одна дилемма. С одной стороны хотелось написать побольше примеров из радиотехники, электродинамики и антенн, которые мне ближе по работе. Но в то же время, это были бы слишком узкоспециализированные примеры, и читатели, которые не знакомы с этой областью, отвлекались бы от языка и описания библиотек в попытке понять, а что мы вообще делаем? Я когда-то сам обжегся на одной книжке про SciPy, в которых рассматривались примеры из биологии и других наук, и я тупо не понимал примеры, потому что был не в курсе предметной области. Поэтому в своей книжке старался описать более общие вопросы, с которыми сталкивается инженер, оставив особо специализированные примеры на последние две главы.
В третьей части нужно было более подробно описать массивы из NumPy (после них массивы из стандартного модуля array становятся ненужными), библиотеку Matplotlib для построения графиков разных видов (это мой отдельный интерес), библиотеки Pandas и SciPy. Помимо этого одна глава посвящена разным форматам хранения данных, начиная с текстовых форматов csv и текстовых файлов, где цифры пишутся в столбики, и заканчивая сложным форматом HDF5 и его наследниками.
В предпоследней главе, посвященной SciPy, я уже дал себе волю и ушел радиотехнические задачи - расчет эффективной площади рассеяния шара, где используются функции Бесселя, и анализ спектров сигналов с описанием различных видов преобразования Фурье.
И в завершении обязательно хотелось рассказать про JupyterLab, а для этого надо было сначала рассказать о его прародителе - проект IPython и более удобную консоль, которую он предоставляет со специальными магическими командами.
В книге я ориентировался на Python 3.13 (когда начинал писать текст, он был еще в стадии бета-версии), но в процессе окончательной подготовки текста уже можно было пощупать альфа-версии Python 3.14. В некоторых местах я добавил к нему отсылки и несколько примеров, показывающие некоторые возможности, которые были только что добавлены (в основном это касается класса Path из модуля pathlib).
Как я писал книгу
Планируемые 500 страниц будущей книги меня не пугали. Изначально я думал, что напишу их до конца 2024 года - за 7 месяцев, а потом возьмусь за окончательное редактирование получившегося текста. К счастью, оглавление было уже достаточно хорошо проработано, был материал в виде исходников и презентаций, подготовленный для студентов, оставалось только взять и заполнить текст между намеченными заголовками (в результате почти все исходники для книги я переделал, а из презентаций в текст попало только несколько картинок). На самом деле каждая глава у меня была оформлена в отдельном файле в формате docx, а набирал текст я в LibreOffice Writer, работая в Manjaro Linux.
Когда я только начал писать текст книги, то понял, что мне нужно какое-то средство, чтобы видеть прогресс и оценивать, насколько я отстаю от плана (кажется, еще ни один живой человек в мире не опережал намеченный план). Для этого я завел файл с электронными таблицами в LibreOffice Calc. Этот файл содержал три страницы. На первой из них была таблица с подсчетом количества страниц в каждой главе:
Вторая страница была такая же, только вместо страниц я там писал количество символов. Эта информация оказалась бесполезной.
А на третьей странице файла подсчитывалось суммарное количество страниц книги, количество символов (как я уже сказал, это оказалось лишнее) и еще я там записывал количество завершенных глав - дробные части для недописанных глав я считал, исходя из количества написанных разделов внутри главы по сравнению с запланированными.
И в итоге на основе суммарного количества страниц строились два графика: количество страниц и количество написанных глав в зависимости от даты:
Это была очень полезная статистика, которую я раз в месяц выкладывал у себя в Телеграм-канале, отчитываясь перед подписчиками о проделанной работе. Это хорошо стимулировало продолжать работать.
Текст я писал в достаточно спокойном ритме. Из графика видно, что прогресс был практически линейным. Сначала процесс шел медленно, но это во многом было связано с тем, что первые главы, которые по сути были введением, писать было тяжелее всего, потом, когда дело дошло непосредственно до описания языка, стало проще. К тому же, в начале я пробовал разные стили написания (более серьезный или более расслабленный), договаривался сам с собой по поводу используемой терминологии (составил себе список используемых слов). Потом где-то на месяц случился заметный подъем (это у меня начался отпуск), а затем скорость прибавления страниц оставалась примерно на одном уровне.
Книгу я писал в основном после работы, где-то по два часа за вечер, каких-то ночных авралов у меня не было. Если в выходные я оставался дома, то старался в эти дни написать побольше. Получалось, что на главу уходила неделя или две в зависимости от ее объема. При этом, когда я писал главу, то я ее почти никогда не перечитывал, оставив это дело на второй этап работы, который начался после того, как все главы были написаны. Так я делал специально, чтобы потом посмотреть на написанный текст свежим взглядом, и с учетом того, что будет написано далее, где-то расставить ссылки на написанные главы.
В процессе работы оказалось, что практически ни одна из глав в запланированный объем не умещается, все они были на 5-10 страниц длиннее. Я уже морально готовился к тому, что придется что-то сокращать (в первую очередь я был готов пустить под нож главу про тестирование). К счастью, оказалось, что тот объем, который получается, тоже приемлем, главное все-таки не превысить 700 страниц. В конце концов ничего сокращать не пришлось. Но из-за этого до конца года я не успевал дописать все главы, как планировал изначально. В итоге последнюю главу я закончил писать к концу марта 2025 года. Времени на вычитку и редактирование оставалось все меньше, и это меня начало напрягать.
Начиная с этого момента работа переключилась в новый режим. В процессе предварительной правки каждая глава проходила хотя бы две итерации перечитывания. Сначала я перечитывал главу и вносил крупные исправления, потом перечитывал ее заново и правок было уже поменьше. Если было подозрение, что нужна еще одна итерация, то перечитывал еще раз. При этом окончательно оформлял текст согласно требованиям издательства.
В этом режиме перестала работать статистика, о которой писал выше, ведь теперь количество страниц перестало быть показателем, а следить за прогрессом как-то надо. Тогда я себе завел что-то вроде лог-файла, только на бумаге. В те дни, когда я вносил какие-то правки, я писал, до какой страницы какой главы дошел, сколько глав осталось перечитать и исправить.
К этому моменту несколько читателей моего Телеграм-канала согласились выступить в качестве бета-тестеров книги. После правки каждой главы я отправлял им то, что получалось. Они присылали свои замечания, и с некоторым временным лагом я их вносил в текст. Это было очень полезно. Помимо стилистических и орфографических ошибок, они вылавливали ошибки в коде и неточности формулировок. Благодаря им в тексте более аккуратно стали использоваться такие термины как "оператор", "выражение", "инструкция" и т.д., не сводя все к слову "оператор". Некоторые места я дополнял новым текстом, но старался не увеличивать общий объем, помня о том, что текст не должен распухать дальше. Честно говоря, в процессе редактирования я надеялся сократить текст, но получалось наоборот - каждая глава увеличивалась еще где-то на страницу-две. Я себя успокаивал тем, что потом в издательстве специально обученные люди включат перенос слов, аккуратно расставят рисунки в процессе верстки, и объем немножко сожмется.
В конце июня этого (2025) года я отправил текст в издательство. Теперь можно было немножко перевести дух. У меня было полтора месяца отдыха, пока для проекта в издательстве не назначат редактора, и он не начнет выполнять свою работу. Затем началась работа с редактором. Надо сказать, что задачей редактора было выправить стиль текста, не исказив при этом суть. Редактор присылал файл с правками (их было дикое количество), я еще раз перечитывал главы (в который раз! Сколько можно!?). С правками я в основном соглашался, что-то исправлял еще раз и отправлял обратно редактору. Интересно, что в процессе редактирования до отправки в издательство я старался сделать текст более сухим, убирая фразы вроде "таким образом", "а также " и т.п., а редактор наоборот делал текст более живым. В таком режиме мы с ним работали месяца полтора.
После этого опять можно было какое-то время отдохнуть - текст отдали на верстку. В это время мы обсудили и утвердили обложку. Где-то через месяц (в конце октября) мне прислали верстку книги. Надо было ее еще раз перечитать (опять!) и выявить проблемные места. Поскольку в этот раз в основном надо было смотреть на оформление, а не на суть, то 670 страниц книги я осилил где-то за неделю. Отметил проблемные моменты и отослал обратно в издательство.
После этого я уже книгу не видел, ее начали готовить к отправке в типографию. В конце ноября этого года книжка появилась на сайте издательства, бумажная версия пришла ближе к началу декабря. А недавно я получил авторские экземпляры книги.
Сейчас я постепенно рассылаю экземпляры книги тем, кому обещал отправить подписанные версии - тем, кто помогал и вычитывал текст.
На этом можно поставить себе галочку в итогах года, что удалось завершить работу над книгой. И, конечно, всем огромное спасибо: и тем, кто читал бета-версию, и работникам издательства (сколько людей над ней работало!) Это был интересный опыт. Надеюсь, что эта книга хоть кому-нибудь пригодится :).