Бэктрекин без рекурсии на Python

В Python нет оптимизации хвостовой рекурсии и достаточно жёсткий лимит на рекурсивные вызовы. Это может вызвать затруднения при решении задач с помощью алгоритма бэктрекинга: лимита хватает на поиск решения судоку, но он может оказаться слишком низким, если количество решений для проверки в задаче довольно высоко. Тем не менее реализация бэктрекинга с рекурсией на Python элегантна, легко читаема и понятна. Отказываться от неё имеет смысл только для «тяжёлых» задач. def backtrack(self, solution): if solution in self.seen_solutions: return if self.reject(solution): return if self.accept(solution): self.output(solution) for child_solution in self.child_solutions(solution): self.backtrack(child_solution) Когда сложность задачи достигнет лимита рекурсивных вызовов, можно переключиться на шаблон без рекурсии. Он уже не так элегантен, как рекурсивное решение, но не так страшен, как мог бы быть. К тому же он использует те же вспомогательные функции, что и его собрат с рекурсией. ...

3 ноября 2016 г.

Обзор курса Functional Programming Principles in Scala

Этой осенью я закончил курс на Coursera «Functional Programming Principles in Scala». Этот курс — часть специализации из 5 курсов «Functional Programming in Scala». Это шестинедельное введение в функциональное программирование и Scala. Автор курса — Мартин Одерски, создатель языка Scala. Он действительно великий учёный в области компьютерных наук. Тем не менее от его лекций клонит в сон. В общем‑то с его лекциями всё в порядке — просто я не сразу нашёл правильный способ прохождения курса: сначала надо пытаться решить практическую задачу, а потом с кучей готовых вопросов смотреть лекции. Так его лекции гораздо полезнее. ...

24 октября 2016 г.

Хочется добавить тип локальной переменной? Пора делать рефакторинг!

PEP 526 добавляет, начиная с Python 3.6, опциональную возможность указать тип для локальной переменной. Это более стройная замена комментариям с указанием типа. Это хорошо, но есть одна ловушка: указание типа в Python может скрыть проблемы в коде. Эти аннотации придуманы и сделаны в основном для автоматических анализаторов кода. Python позволяет писать понятный людям код и без дополнительного указания типа переменной. Поэтому, если есть желание добавить к переменной такое определение, — вы в беде. Это последнее средство для увеличения читаемости кода, а не первое. ...

6 октября 2016 г.

MongoDB count могут сильно замедлить API

Иногда команда фронтенда или другие потребители API просят выводить в эндпоинтах общее число объектов. Если в качестве хранилища используется MongoDB, постарайтесь избежать этого: такое поведение эндпоинтов может значительно их замедлить. Я говорю о тех случаях, когда ответ API похож на тот, что расположен ниже, — тогда ждите беды: { "total": XX, "limit": ZZ, "offset": YY, "objects": [...] } Если коллекция достаточно большая, а запрос достаточно тяжёлый, count будет работать непозволительно долго. Запрос find при этом может работать быстро: ему ведь надо вернуть всего‑то десяток объектов. count будет перебирать весь набор объектов, подходящих под условия запроса. ...

23 сентября 2016 г.

Не используйте dict так часто

У разработчиков на Python наблюдается тенденция использовать словари (дикты) там, где нужно, и там, где нет. В основном это касается передачи данных внутри приложения в виде словаря (дикта), вместо создания объекта. Это плохой дизайн, который приводит к целому вороху проблем, самая страшная из которых — такой код невозможно читать. К примеру, есть код, который вызывает внешнее API и получает в ответ JSON, который уже распарсили в dict. Стоит мне отправлять этот словарь дальше или лучше трансформировать его в экземпляр более специфического класса? Оба варианта возможны. Обычно я предпочитаю использовать классы и объекты, хотя это требует определённых усилий и времени: соответствующий класс надо ещё написать. ...

9 сентября 2016 г.

Переезд с Python на Java. Первые впечатления

Буквально неделю назад я добавил Java в свой рабочий стек технологий: мы начали делать новый проект с использованием Java Spring Framework. Для меня это интересный вызов. Я никогда раньше не использовал Java, кроме как для маленьких домашних проектов. Вот мои самые первые впечатления о «лютом энтерпрайзе». Я не хочу сравнивать Python и Java как языки программирования. Очевидно, что в Java есть статическая типизация, а в Python — нет. Очевидно, что Java более многословна, а Python — более компактен. Всё это не так интересно. Гораздо интереснее сравнить окружение языков, требуемый ими подход к программированию. ...

26 августа 2016 г.

mypy для проекта на Python 2.7

Аннотация типов может сильно помочь при работе над большим проектом на Python: многие ошибки в дизайне и использовании функций выявляются практически сразу. Конечно, для этого требуется использование внешних инструментов для статического анализа, таких как MyPy. Это великолепный инструмент, но он поддерживает третью ветку Python. Поддержка Python 2.7 в нём требует некоторой подготовки. Type comments vs stub files Для начала нужно определиться, как аннотировать типы в коде. Для второй ветки Python есть два варианта: аннотирование в комментариях или использование стаб‑файлов. Я предпочитаю первый путь: он информативнее (типы перед глазами) и его легче поддерживать. ...

29 июля 2016 г.

Пишем код для Unity3d в Sublime Text 3

Необходимость использовать MonoDevelop — пожалуй, худшая часть разработки игр под Unity. Для пользователей Windows теперь есть альтернатива: они могут использовать Visual Studio. Что делать счастливым обладателям Mac? Переключаться на Sublime Text. Правда, в сети не так много информации о том, как это сделать. Я потратил достаточно много времени, чтобы разобраться, как настроить автодополнение для C# в Sublime Text. В итоге я нашёл достаточно простой путь, требующий всего трёх вещей, установленных на Mac: ...

22 июля 2016 г.

TrueType шрифты в LibGDX

LibGDX — прекрасная библиотека. Её очень легко использовать, хотя в ней есть некоторые аспекты, которые не так просты и понятны. Шрифты — один из примеров. Я провёл много часов, прежде чем нашёл решение, при котором шрифты и на десктопе, и в мобильных телефонах выглядят пристойно. Я уже писал, что у меня получилось добиться результатов с Distance Field, но я ошибался. Заставить хорошо выглядеть удалось только TTF. Забудьте о bitmap‑шрифтах. На попытки заставить их выглядеть пристойно на всех девайсах уйдёт уйма времени. Результат при этом будет более чем посредственным — даже несмотря на то, что это более или менее рекомендованный путь. Но всё‑таки, если у вас не сотни шрифтов, лучше использовать TrueType Fonts. ...

14 июля 2016 г.

Свой итератор поверх enumerate

ППару дней назад коллега попросил сделать логирующий сам себя итератор поверх enumerate. Я попробовал наследоваться напрямую и потерпел неудачу. Я абсолютно забыл, как работает магический метод __new__. Поскольку я был занят, я пообещал себе разобраться с этой проблемой позже. А ларчик открывался очень просто: 18 строк кода — и у меня появилась нужная функциональность. Изначальная задача Сначала стоит объяснить, зачем нам вообще понадобился подобный итератор и почему нам не хватило обычного enumerate. Всё дело в том, что у нас в проекте очень много задач, построенных по такому шаблону: ...

27 июня 2016 г.