<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>Разработка on Лаборатория</title>
    <link>https://www.alexkorablev.ru/dev/</link>
    <description>Recent content in Разработка on Лаборатория</description>
    <generator>Hugo</generator>
    <language>ru-ru</language>
    <lastBuildDate>Mon, 23 Mar 2026 21:40:27 +0500</lastBuildDate>
    <atom:link href="https://www.alexkorablev.ru/dev/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>Вторичные индексы в YDB</title>
      <link>https://www.alexkorablev.ru/dev/ydb-secondary-indexes/</link>
      <pubDate>Mon, 23 Mar 2026 21:40:27 +0500</pubDate>
      <guid>https://www.alexkorablev.ru/dev/ydb-secondary-indexes/</guid>
      <description>&lt;p&gt;Вторичные индексы в YDB живут в скрытых таблицах. Они так же чувствительны к возможности деления на партиции по ключам, как и обычные строковые таблицы.&lt;/p&gt;
&lt;p&gt;Способность делиться на партиции вторичные индесы наследуют от первичного ключа исходной таблицы.&lt;/p&gt;
&lt;p&gt;Согласно документации во вторичном индексе хранится:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;индексные колонки&lt;/li&gt;
&lt;li&gt;колонки первичного ключа таблицы&lt;/li&gt;
&lt;li&gt;копии дополнительных колонок для покрывающих индексов&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;NB!&lt;/strong&gt; первичный ключ таблицы вторичного ключа - это индексные колонки + колонки первичного ключа исходной таблицы.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Посмотреть процессы прибитые OOM</title>
      <link>https://www.alexkorablev.ru/dev/oom/</link>
      <pubDate>Sun, 08 Sep 2024 18:40:16 +0500</pubDate>
      <guid>https://www.alexkorablev.ru/dev/oom/</guid>
      <description>&lt;p&gt;PID убитого по out‑of‑memory‑процессу можно найти с помощью одной команды. Если есть логи с PID процесса, то найти пострадавшего можно, запустив ещё одну команду &lt;code&gt;grep&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;OOM‑киллер безжалостен. Кажется, что он выбирает процесс случайным образом — тот, который нужно «пристрелить» на машине. На самом деле под капотом он работает совсем по‑другому, и случайности в его действиях нет. Взглянув на таблицу процессов и пару файлов, можно предсказать, какой процесс будет убит, если сейчас случится OOM.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Практический пример использования Protocol</title>
      <link>https://www.alexkorablev.ru/dev/protocol/</link>
      <pubDate>Mon, 26 Feb 2024 18:36:23 +0500</pubDate>
      <guid>https://www.alexkorablev.ru/dev/protocol/</guid>
      <description>&lt;p&gt;Представьте себе ситуацию: у вас есть микросервисы, в каждом — своя конфигурация со своим набором параметров; есть библиотечный код, который получает и использует объекты конфигураций. Представили? А теперь в этот код надо завести подсказки типов. И тут представили? Давайте проведём мысленный эксперимент и попробуем это сделать. Вариантов в целом несколько.&lt;/p&gt;
&lt;p&gt;Варианты решения:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Базовый класс конфигурации с ещё одним ветвлением:*
&lt;ul&gt;
&lt;li&gt;затаскивать все возможные параметры;&lt;/li&gt;
&lt;li&gt;затаскивать только общие для микросервисов параметры.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Использовать протоколы для нотации типов.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Затаскивать все возможные варианты параметров в один базовый класс — гарантированный путь к «помойке». Затаскивать только общие параметры для микросервисов — получать кучу красного цвета от Pyright в общем коде.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Использование typing.Generic в Python</title>
      <link>https://www.alexkorablev.ru/dev/generics-in-python/</link>
      <pubDate>Fri, 18 Feb 2022 18:28:28 +0500</pubDate>
      <guid>https://www.alexkorablev.ru/dev/generics-in-python/</guid>
      <description>&lt;p&gt;Я работаю над проектом с довольно большой кодовой базой. Проект с историей.&lt;/p&gt;
&lt;p&gt;Некоторые части наша команда написала задолго до аннотаций типов. Мы до сих пор добавляем их в наш легаси‑код и улучшаем существующие подсказки. Стоит ли эта игра свеч? Определённо — да.&lt;/p&gt;
&lt;p&gt;Наши пользователи — разработчики. Они открывают наш код в PyCharm ежедневно и надеются, что он поможет им решить их задачи максимально быстро и просто.&lt;/p&gt;
&lt;p&gt;Могу уверенно сказать, что существует корреляция между точностью автодополнения кода и тем, как быстро работают разработчики. Наша цель — не только добавить более точный статический анализ или автодополнение, но и не сломать их боевой код.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Для чего Python лучше не использовать?</title>
      <link>https://www.alexkorablev.ru/dev/what-is-python-not-good-for/</link>
      <pubDate>Fri, 22 Nov 2019 18:26:11 +0500</pubDate>
      <guid>https://www.alexkorablev.ru/dev/what-is-python-not-good-for/</guid>
      <description>&lt;p&gt;На Quora относительно недавно задали вопрос «What is Python not good for?». Я бы хотел сказать, что Python хорош для всего. Но это неправда. Python во многих областях — второй. Не так много областей, где Python — номер один.&lt;/p&gt;
&lt;p&gt;К примеру, Go сейчас гораздо больше подходит для веб‑разработки, чем Python. Его довольно легко выучить, его гораздо легче деплоить. В Go есть достаточное количество «батареек» для любого веб‑приложения. Тем не менее Python остаётся второй опцией.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Подсказки типов в Python</title>
      <link>https://www.alexkorablev.ru/dev/python-typing-hints-list/</link>
      <pubDate>Fri, 24 May 2019 18:22:15 +0500</pubDate>
      <guid>https://www.alexkorablev.ru/dev/python-typing-hints-list/</guid>
      <description>&lt;p&gt;Мой небольшой список источников по type hints в Python, которые я использую в повседневной практике.&lt;/p&gt;
&lt;p&gt;Относительно недавно я сменил проект. Теперь я работаю над DWH и ETL‑процессами. Проект большой: в нём сравнимое количество кода с предыдущим, но разработчиков гораздо больше. Я убеждён, что для этого проекта подсказки типов даже нужнее. Дело не только в количестве разработчиков.&lt;/p&gt;
&lt;p&gt;Особенность DWH/ETL‑проектов — наличие разнообразных источников, мест хранения и потребителей данных. Отсюда довольно сильная фрагментированность проекта. И если не добавить «клея», он развалится на отдельные скрипты.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Clash of Code</title>
      <link>https://www.alexkorablev.ru/dev/clash-of-code/</link>
      <pubDate>Fri, 26 Apr 2019 18:20:27 +0500</pubDate>
      <guid>https://www.alexkorablev.ru/dev/clash-of-code/</guid>
      <description>&lt;p&gt;В начале года я &lt;a href=&#34;%7Bfilename%7D/2019-01-02-2019-plans.md&#34;&gt;писал&lt;/a&gt;, что хочу сделать большой и интересный проект с &lt;a href=&#34;https://www.codingame.com&#34;&gt;Codingame&lt;/a&gt;: создать и обучить бота для &lt;em&gt;Legends of Code &amp;amp; Magic&lt;/em&gt;. В очередной раз, когда я прокрастинировал начало этого проекта, я наткнулся на &lt;a href=&#34;https://www.codingame.com/multiplayer/clashofcode&#34;&gt;Clash of Code!&lt;/a&gt; — быстрые мини‑соревнования по кодированию на этом же сайте. Попробовав поиграть, я могу сказать, что это отличный способ отвлечься от рабочей рутины, попутно потренировав свои навыки.&lt;/p&gt;
&lt;h2 id=&#34;формат-clash-of-code&#34;&gt;Формат Clash of Code&lt;/h2&gt;
&lt;p&gt;Эти мини‑соревнования строятся по такому принципу:&lt;/p&gt;</description>
    </item>
    <item>
      <title>Переименование при импорте</title>
      <link>https://www.alexkorablev.ru/dev/import-aliases/</link>
      <pubDate>Mon, 18 Mar 2019 18:18:34 +0500</pubDate>
      <guid>https://www.alexkorablev.ru/dev/import-aliases/</guid>
      <description>&lt;p&gt;В Python есть замечательная возможность присваивать свои имена при импорте (&lt;code&gt;import foo.bar.baz as fbb&lt;/code&gt;). Так можно легко избежать конфликтов имён при импорте и повысить читаемость кода, если требуется. Но этой же возможностью можно легко превратить хороший код в абсолютно нечитаемый. В последнее время я несколько раз встречался с этим: попадались мне в основном странные сокращения и непонятные имена для алиасов.&lt;/p&gt;
&lt;p&gt;Продемонстрирую проблему на примере сокращений. Хороший пример придумать с ними проще:&lt;/p&gt;</description>
    </item>
    <item>
      <title>Пожалуйста, не используйте else</title>
      <link>https://www.alexkorablev.ru/dev/if-else/</link>
      <pubDate>Tue, 29 Jan 2019 18:15:47 +0500</pubDate>
      <guid>https://www.alexkorablev.ru/dev/if-else/</guid>
      <description>&lt;p&gt;Я не люблю &lt;code&gt;else&lt;/code&gt;, когда обе ветки содержат &lt;code&gt;return&lt;/code&gt;. Всегда можно написать код без этого придатка для &lt;code&gt;if&lt;/code&gt;. Такой код будет компактнее, проще читаться и лучше выглядеть. Так зачем же многие пишут этот никчёмный &lt;code&gt;else&lt;/code&gt;?&lt;/p&gt;
&lt;p&gt;Делая ревью кода одного из коллег, я указал на то, что его код можно упростить, убрав &lt;code&gt;else&lt;/code&gt;. Ответом была ссылка на PEP8, где такое поведение определяется допустимым. Код был примерно таким:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;get_magic_number&lt;/span&gt;(use_magic):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; use_magic:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; calculate_with_magic()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;else&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; calculate_with_science()
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;С точки зрения работоспособности этому коду нечего предъявить. Меня, как читателя, такой код заставляет остановиться и задуматься:&lt;/p&gt;</description>
    </item>
    <item>
      <title>Мобильное приложение на Kivy и Python? Мм… Не сейчас</title>
      <link>https://www.alexkorablev.ru/dev/kivy-mobile/</link>
      <pubDate>Thu, 25 Oct 2018 16:47:52 +0500</pubDate>
      <guid>https://www.alexkorablev.ru/dev/kivy-mobile/</guid>
      <description>&lt;p&gt;Есть несколько GUI‑фреймворков на Python. Большинство из них предназначены только для десктопных приложений. Kivy — редкое исключение: с использованием этого фреймворка можно, в теории, строить мобильные приложения. К сожалению, он не готов к продакшену. Вы вынуждены жонглировать версиями библиотек, чтобы заставить это работать. Так что, даже сидя в футболке с надписью &lt;code&gt;print(&amp;quot;Python is my favorite language&amp;quot;)&lt;/code&gt;, я должен признать, что Kivy не подходит для мобильной разработки.&lt;/p&gt;
&lt;p&gt;Хорошо. Жонглировать версиями приходится и в случае веб‑приложения. Но всё‑таки тогда в 99 % случаев речь идёт о библиотеках Python либо есть контроль над окружением. В целом вы можете построить Docker‑образ с любыми версиями, какие необходимы. Kivy же вносит кучу бинарных зависимостей, которые должны быть установлены с помощью специфичных для платформ инструментов. И в целом вы не сможете контролировать окружение — а это меняет всё.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Использовать Optional в абстрактных классах или нет?</title>
      <link>https://www.alexkorablev.ru/dev/optional-or-not/</link>
      <pubDate>Thu, 06 Sep 2018 16:45:46 +0500</pubDate>
      <guid>https://www.alexkorablev.ru/dev/optional-or-not/</guid>
      <description>&lt;p&gt;Подсказки типов в Python необязательны: вы вольны выбирать, пользоваться ими или нет. Но, начав включать их в свой код, вы точно столкнётесь с определёнными трудностями аннотирования функций или переменных. Эта статья — моя точка зрения на один специфический случай.&lt;/p&gt;
&lt;p&gt;К примеру, имеется иерархия классов, которая выглядит похожей на ту, что представлена в коде ниже. Это может быть какой‑то маппинг в базу или иерархия команд. Самая важная часть в этом примере — то, что имеется один абстрактный класс и несколько реальных классов, его наследников. Не так важно, помечен ли этот абстрактный класс специальным образом или нет. Я просто предполагаю, что он используется в качестве такового.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Coders Strike Back Post-mortem</title>
      <link>https://www.alexkorablev.ru/dev/coders-strike-back/</link>
      <pubDate>Thu, 12 Jul 2018 16:42:09 +0500</pubDate>
      <guid>https://www.alexkorablev.ru/dev/coders-strike-back/</guid>
      <description>&lt;p&gt;За последние несколько месяцев я потратил порядка 40 часов в выходные и по вечерам на то, чтобы написать бота, способного пройти трассу &lt;a href=&#34;https://www.codingame.com/multiplayer/bot-programming/coders-strike-back&#34;&gt;Coders Strike Back&lt;/a&gt; быстрее соперников. За эти 40 часов я умудрился набить порядочное количество шишек, выбраться в легендарную лигу и даже занять там, на мой взгляд, пристойное место. Данный пост — post mortem этого проекта.&lt;/p&gt;
&lt;p&gt;Важная оговорка: бо́льшая часть пути была проделана с ботами на Python, но заключительные этапы были пройдены на C++. Не думаю, что дело в Python — скорее всего, я не заметил кучу ошибок в своём коде, которые было лень исправлять, но об этом ниже.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Computer Science Distilled</title>
      <link>https://www.alexkorablev.ru/dev/computer-science-distilled/</link>
      <pubDate>Wed, 28 Feb 2018 16:38:43 +0500</pubDate>
      <guid>https://www.alexkorablev.ru/dev/computer-science-distilled/</guid>
      <description>&lt;p&gt;Хотите найти небольшую простую книгу о компьютерных науках? Возможно, &lt;a href=&#34;https://sourcemaking.com/computer-science-distilled&#34;&gt;Computer Science Distilled&lt;/a&gt; подойдёт. К сожалению, только в том случае, если вы не планируете программировать профессионально. В этом случае эта книга — хороший вводный курс, хороший проводник в мир компьютерных наук. Но если вы профессиональный девелопер или студент, можно смело пропускать эту книгу.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;It’s a short book, written in plain, basic English. It presents ideas in their simplest form. It focuses on practical aspects of computer science that matter most: everyday things that directly impact the quality of your code.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Tuple[Callable, Any, ...]</title>
      <link>https://www.alexkorablev.ru/dev/tuple-type/</link>
      <pubDate>Mon, 29 Jan 2018 16:35:53 +0500</pubDate>
      <guid>https://www.alexkorablev.ru/dev/tuple-type/</guid>
      <description>&lt;p&gt;Подсказки с типами могут сильно помочь в работе с большим проектом на Python. Тем не менее иногда они требуют рефакторинга кода. Я писал об этом в прошлом году &lt;a href=&#34;%7Bfilename%7D2017-11-10-typing-ci.md&#34;&gt;в этой статье&lt;/a&gt;, но тогда я не смог найти хорошего примера, иллюстрирующего то, что я хочу сказать.&lt;/p&gt;
&lt;p&gt;Взгляните на этот код:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;process&lt;/span&gt;(workflow_step):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    func &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; step[&lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    args &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; step[&lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;:]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; func(&lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;args)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Что можно понять о типах из этого кусочка? То, что &lt;code&gt;workflow_step&lt;/code&gt; — это последовательность, первый элемент которой — &lt;code&gt;Callable&lt;/code&gt; object, а остальные элементы, если таковые имеются, — аргументы для этого вызываемого объекта. Предположим, что &lt;code&gt;workflow_step&lt;/code&gt; — &lt;code&gt;Tuple&lt;/code&gt;. Проблема в том, что тип &lt;code&gt;(Tuple) -&amp;gt; Any&lt;/code&gt; для этой функции слишком общий и неинформативный. Можем ли мы вызвать её с пустым кортежем? Пройдёт ли &lt;code&gt;(1, 2, 3)&lt;/code&gt;?&lt;/p&gt;</description>
    </item>
    <item>
      <title>Как внедрить mypy в проекте на Python 2.7</title>
      <link>https://www.alexkorablev.ru/dev/typing-ci/</link>
      <pubDate>Mon, 11 Dec 2017 17:34:15 +0500</pubDate>
      <guid>https://www.alexkorablev.ru/dev/typing-ci/</guid>
      <description>&lt;p&gt;Я многократно писал, что описание типов в Python помогает в работе с большими и средними проектами. При этом, если внедрять типы, то нужно регулярно делать статический анализ — причём в CI. А вот это уже не так‑то просто внедрить. Эта статья — мой рассказ о том, какие трудности придётся преодолеть в процессе внедрения.&lt;/p&gt;
&lt;p&gt;За то время, что я пытаюсь внедрить проверку типов в нашем проекте, я выработал несколько подходов к тому, как это можно сделать максимально быстро и безболезненно. На то, чтобы прийти к этому, я убил не один день. Пользуйтесь моим опытом.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Что почитать о asyncio. 9 полезных ссылок</title>
      <link>https://www.alexkorablev.ru/dev/asyncio-articles/</link>
      <pubDate>Fri, 20 Oct 2017 17:31:50 +0500</pubDate>
      <guid>https://www.alexkorablev.ru/dev/asyncio-articles/</guid>
      <description>&lt;p&gt;Asyncio — полезная библиотека. Но разобраться с ней не так‑то просто. Документации по большей части недостаточно. Хочется примеров. Хочется подробных объяснений. Последние несколько выходных я потратил на эксперименты с этой библиотекой. Во время чего в Pocket осели довольно интересные ссылки, которыми я хочу поделиться.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&#34;http://www.giantflyingsaucer.com/blog/?p=5557&#34;&gt;Exploring Python 3’s Asyncio by Example&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Короткое введение в &lt;code&gt;asyncio&lt;/code&gt; и &lt;code&gt;aiohttp&lt;/code&gt; на нескольких небольших примерах. Примеры сделаны максимально простыми. Используется синтаксис с декораторами — статья написана довольно давно. Как отмечает автор, эта статья показывает лишь верхушку айсберга.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Поддержка целостности проекта в Python требует усилий</title>
      <link>https://www.alexkorablev.ru/dev/python-project-integrity/</link>
      <pubDate>Fri, 06 Oct 2017 17:28:58 +0500</pubDate>
      <guid>https://www.alexkorablev.ru/dev/python-project-integrity/</guid>
      <description>&lt;p&gt;Python позволяет программисту довольно много. Это очень выразительный язык. Его динамическая природа даёт возможность делать элегантные решения, которые довольно сложно представить, к примеру, в Java.&lt;/p&gt;
&lt;p&gt;Тем не менее за всё надо платить. При росте кодовой базы проекты на Python начинают требовать всё больше и больше ресурсов на поддержание своей целостности. Без некоторых усилий проект начинает разваливаться на куски.&lt;/p&gt;
&lt;h2 id=&#34;первая-проблема--навигация-по-коду&#34;&gt;Первая проблема — навигация по коду&lt;/h2&gt;
&lt;p&gt;Основная проблемная часть — навигация по коду. На начальном этапе её зачастую приносят в жертву более компактному решению, что впоследствии обязательно приведёт к ряду проблем. Главная из которых — высокая сложность поиска причин ошибок.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Хэш-функция для функции в Python</title>
      <link>https://www.alexkorablev.ru/dev/function-hash/</link>
      <pubDate>Tue, 12 Sep 2017 17:26:17 +0500</pubDate>
      <guid>https://www.alexkorablev.ru/dev/function-hash/</guid>
      <description>&lt;p&gt;Пару недель назад один из моих коллег задал вопрос: можно ли использовать функцию в качестве ключа словаря? Да, можно. У каждой функции в Python есть хеш. Но как он считается? На основе имени функции? На основе байт‑кода? В действительности хэш считается как трансформация над указателем на объект функции. Тем не менее не так‑то легко отыскать эти расчёты в коде CPython.&lt;/p&gt;
&lt;p&gt;Навигация по C‑коду — довольно интересный опыт, хотя делать это совсем непросто: все эти макросы делают простой поиск нужных переходов довольно сложным. Конечно, я уверен, что вы сможете с этим справиться и найти все вызываемые функции при запросе хеша для объекта функции.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Структуры данных и алгоритмы в Java (2-е издание)</title>
      <link>https://www.alexkorablev.ru/dev/lafore-java/</link>
      <pubDate>Tue, 15 Aug 2017 17:29:21 +0500</pubDate>
      <guid>https://www.alexkorablev.ru/dev/lafore-java/</guid>
      <description>&lt;p&gt;Для меня основное достоинство книги «&lt;a href=&#34;https://www.piter.com/product/struktury-dannyh-i-algoritmy-v-java-klassika-computers-science-2-e-izd&#34;&gt;Структуры данных и алгоритмы в Java&lt;/a&gt;» — язык, которым автор описывает алгоритмы. Он не использует сложный академический язык, приправленный тонной высшей математики. Роберт Лафоре использует простой язык и пытается дать максимально простое объяснение, какое только возможно, каждому алгоритму.&lt;/p&gt;
&lt;h2 id=&#34;почему-эта-книга&#34;&gt;Почему эта книга?&lt;/h2&gt;
&lt;p&gt;Эта книга — для занятых (или ленивых) студентов или программистов, которые решили повторить алгоритмы перед техническим интервью. Книгу можно просмотреть очень быстро: читаем список идей после каждой статьи, просматриваем примеры кода. Если что‑то показалось непонятным, возвращаемся к основному тексту главы.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Горячие клавиши Emacs в русской раскладке</title>
      <link>https://www.alexkorablev.ru/dev/emacs-got-keys/</link>
      <pubDate>Sat, 10 Jun 2017 17:27:10 +0500</pubDate>
      <guid>https://www.alexkorablev.ru/dev/emacs-got-keys/</guid>
      <description>&lt;p&gt;Думаю, вы, как и я, не можете позволить себе пользоваться только английской раскладкой клавиатуры. Так или иначе для работы приходится использовать обе: и русскую, и английскую. В целом это не доставляет никаких проблем, пока дело не касается Emacs.&lt;/p&gt;
&lt;p&gt;Не знаю почему, но в нём горячие клавиши в русской раскладке просто перестают работать. Видимо, сказывается страшное наследие «ASCII — единственно возможный набор символов для всех языков мира». Возможно, есть какие‑то другие причины.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Property в классе наследнике</title>
      <link>https://www.alexkorablev.ru/dev/property-and-inheritance/</link>
      <pubDate>Tue, 30 May 2017 17:25:13 +0500</pubDate>
      <guid>https://www.alexkorablev.ru/dev/property-and-inheritance/</guid>
      <description>&lt;p&gt;Кажется очевидным, что &lt;code&gt;property&lt;/code&gt; можно переопределить в классе‑наследнике и вызвать &lt;code&gt;super&lt;/code&gt; внутри этого переопределённого свойства. Вроде бы звучит нормально? Да, так и есть. Тем не менее, когда мой коллега задал мне такой вопрос, я «завис» на некоторое время. Возможно, я излишне подозрителен, но каждый раз, когда в коде есть какая‑то магия, я ожидаю подвоха. Поэтому я решил немного поэкспериментировать и доказать себе, что свойства (&lt;code&gt;property&lt;/code&gt;) работают так, как ожидается.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# -*- coding: utf-8 -*-&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;from&lt;/span&gt; __future__ &lt;span style=&#34;color:#f92672&#34;&gt;import&lt;/span&gt; print_function, unicode_literals, absolute_import
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Parent&lt;/span&gt;(object):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;@property&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;prop&lt;/span&gt;(self):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        print(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Parent property&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Child&lt;/span&gt;(Parent):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;@property&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;prop&lt;/span&gt;(self):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        super(Child, self)&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;prop
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        print(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Child property&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;child &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; Child()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;child&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;prop
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Работает, как и ожидалось:&lt;/p&gt;</description>
    </item>
    <item>
      <title>Pyenv на маке</title>
      <link>https://www.alexkorablev.ru/dev/pyenv/</link>
      <pubDate>Fri, 19 May 2017 17:23:03 +0500</pubDate>
      <guid>https://www.alexkorablev.ru/dev/pyenv/</guid>
      <description>&lt;p&gt;Довольно сложно управляться с несколькими версиями Python на одном ноутбуке. Хотя это довольно распространённая ситуация. Обычно у разработчиков несколько проектов, требующих разных версий Python. В целом есть несколько вариантов для решения этой задачи, но моим любимым остаётся &lt;a href=&#34;https://github.com/pyenv/pyenv&#34;&gt;pyenv&lt;/a&gt; в компании с плагином &lt;a href=&#34;https://github.com/pyenv/pyenv-virtualenv&#34;&gt;pyenv‑virtualenv&lt;/a&gt;. Раньше я использовал «голый» Homebrew, но это далеко не так гибко и удобно.&lt;/p&gt;
&lt;h2 id=&#34;установка&#34;&gt;Установка&lt;/h2&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ brew update
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ brew install pyenv
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ brew install pyenv-virtualenv
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ echo &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;eval &amp;#34;$(pyenv init -)&amp;#34;&amp;#39;&lt;/span&gt; &amp;gt;&amp;gt; ~/.bash_profile
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ echo &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;eval &amp;#34;$(pyenv virtualenv-init -)&amp;#34;&amp;#39;&lt;/span&gt; &amp;gt;&amp;gt; ~/.bash_profile
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;базовый-шаблон-использования&#34;&gt;Базовый шаблон использования&lt;/h2&gt;
&lt;p&gt;Настоятельно рекомендую делать отдельные виртуальные окружения для каждого проекта. Иногда бывает необходимо делать даже несколько окружений для одного проекта. К примеру, если хочется использовать mypy для проекта на Python 2.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Enums в Python</title>
      <link>https://www.alexkorablev.ru/dev/enums/</link>
      <pubDate>Fri, 17 Feb 2017 22:08:55 +0500</pubDate>
      <guid>https://www.alexkorablev.ru/dev/enums/</guid>
      <description>&lt;p&gt;&lt;code&gt;Enum&lt;/code&gt; — наименее используемая фича Python. Как программисты, мы предпочитаем использовать странные словари (дикты) или списки там, где могли бы использовать &lt;code&gt;enum&lt;/code&gt;. По большей части это происходит из‑за того, что это довольно новая фича, и требуется использовать внешнюю библиотеку обратной совместимости, если используется Python версии 2.7. Тем не менее довольно много случаев, когда использовать &lt;code&gt;enum&lt;/code&gt; гораздо удобнее.&lt;/p&gt;
&lt;p&gt;В любом проекте на Python легко найти код, который делает проверки против строковых литералов. Подобные конструкции используются для определения типов постов, ролей клиентов и тому подобного. Конечно, этот код меняется со временем — меняется набор используемых строковых литералов. Это делает такой код трудноподдерживаемым и труднотестируемым.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Effective Java второе издание</title>
      <link>https://www.alexkorablev.ru/dev/effective-java/</link>
      <pubDate>Fri, 30 Dec 2016 22:03:16 +0500</pubDate>
      <guid>https://www.alexkorablev.ru/dev/effective-java/</guid>
      <description>&lt;p&gt;Если задать вопрос о том, какую книгу стоит прочесть о Java, все скажут, что &lt;a href=&#34;https://www.amazon.com/Effective-Java-2nd-Joshua-Bloch/dp/0321356683&#34;&gt;«Effective Java»&lt;/a&gt;. Эта книга есть во всех списках рекомендованных книг по Java — за исключением, пожалуй, только тех, авторы которых пытаются продать вам свои книги. Есть несколько причин, почему эта довольно старая книга остаётся такой популярной.&lt;/p&gt;
&lt;p&gt;Во‑первых, эта книга учит, как писать хороший Java‑код. Это значит не только быстрый код, но и читаемый, и поддерживаемый. Она описывает общие Java‑паттерны, которые делают ваш код более понятным для других программистов. Книга не рассказывает о том, как «хачить» JVM, — только о том, как использовать её более эффективно.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Делаем Java-подобный Optional в Python</title>
      <link>https://www.alexkorablev.ru/dev/optional-in-python/</link>
      <pubDate>Fri, 25 Nov 2016 22:01:03 +0500</pubDate>
      <guid>https://www.alexkorablev.ru/dev/optional-in-python/</guid>
      <description>&lt;p&gt;В некоторых случаях использование &lt;code&gt;None&lt;/code&gt; может превратить код в нечитаемую и неподдерживаемую кашу. К примеру, если есть необходимость отличить «пустое» значение от отсутствия значения для целочисленного ввода, когда 0 не может использоваться в качестве этого «пустого» значения, обойтись, используя только &lt;code&gt;None&lt;/code&gt;, очень сложно. Одно из возможных решений — использовать что‑то подобное &lt;code&gt;Optional&lt;/code&gt; из Java.&lt;/p&gt;
&lt;p&gt;Конечно, &lt;code&gt;Optional&lt;/code&gt; — не совсем «питонячий» путь. В некоторых случаях можно использовать исключения, как предлагается в &lt;a href=&#34;http://stackoverflow.com/questions/22992433/is-there-a-python-equivalent-for-scalas-option-or-either&#34;&gt;этой дискуссии на Stack Overflow&lt;/a&gt;.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Бэктрекин без рекурсии на Python</title>
      <link>https://www.alexkorablev.ru/dev/python-backtracking/</link>
      <pubDate>Thu, 03 Nov 2016 22:02:16 +0500</pubDate>
      <guid>https://www.alexkorablev.ru/dev/python-backtracking/</guid>
      <description>&lt;p&gt;В Python нет оптимизации хвостовой рекурсии и достаточно жёсткий лимит на рекурсивные вызовы. Это может вызвать затруднения при решении задач с помощью алгоритма бэктрекинга: лимита хватает на поиск решения судоку, но он может оказаться слишком низким, если количество решений для проверки в задаче довольно высоко.&lt;/p&gt;
&lt;p&gt;Тем не менее реализация бэктрекинга с рекурсией на Python элегантна, легко читаема и понятна. Отказываться от неё имеет смысл только для «тяжёлых» задач.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;backtrack&lt;/span&gt;(self, solution):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; solution &lt;span style=&#34;color:#f92672&#34;&gt;in&lt;/span&gt; self&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;seen_solutions:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; self&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;reject(solution):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; self&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;accept(solution):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        self&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;output(solution)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; child_solution &lt;span style=&#34;color:#f92672&#34;&gt;in&lt;/span&gt; self&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;child_solutions(solution):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        self&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;backtrack(child_solution)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Когда сложность задачи достигнет лимита рекурсивных вызовов, можно переключиться на шаблон без рекурсии. Он уже не так элегантен, как рекурсивное решение, но не так страшен, как мог бы быть. К тому же он использует те же вспомогательные функции, что и его собрат с рекурсией.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Обзор курса Functional Programming Principles in Scala</title>
      <link>https://www.alexkorablev.ru/dev/progfun1/</link>
      <pubDate>Mon, 24 Oct 2016 22:00:40 +0500</pubDate>
      <guid>https://www.alexkorablev.ru/dev/progfun1/</guid>
      <description>&lt;p&gt;Этой осенью я закончил курс на Coursera &lt;a href=&#34;https://www.coursera.org/learn/progfun1&#34;&gt;«Functional Programming Principles in Scala»&lt;/a&gt;. Этот курс — часть специализации из 5 курсов «Functional Programming in Scala». Это шестинедельное введение в функциональное программирование и Scala.&lt;/p&gt;
&lt;p&gt;Автор курса — Мартин Одерски, создатель языка Scala. Он действительно великий учёный в области компьютерных наук. Тем не менее от его лекций клонит в сон. В общем‑то с его лекциями всё в порядке — просто я не сразу нашёл правильный способ прохождения курса: сначала надо пытаться решить практическую задачу, а потом с кучей готовых вопросов смотреть лекции. Так его лекции гораздо полезнее.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Хочется добавить тип локальной переменной? Пора делать рефакторинг!</title>
      <link>https://www.alexkorablev.ru/dev/local-variable-type/</link>
      <pubDate>Thu, 06 Oct 2016 21:58:54 +0500</pubDate>
      <guid>https://www.alexkorablev.ru/dev/local-variable-type/</guid>
      <description>&lt;p&gt;&lt;a href=&#34;https://www.python.org/dev/peps/pep-0526/&#34;&gt;PEP 526&lt;/a&gt; добавляет, начиная с Python 3.6, опциональную возможность указать тип для локальной переменной. Это более стройная замена комментариям с указанием типа. Это хорошо, но есть одна ловушка: указание типа в Python может скрыть проблемы в коде.&lt;/p&gt;
&lt;p&gt;Эти аннотации придуманы и сделаны в основном для автоматических анализаторов кода. Python позволяет писать понятный людям код и без дополнительного указания типа переменной. Поэтому, если есть желание добавить к переменной такое определение, — вы в беде. Это последнее средство для увеличения читаемости кода, а не первое.&lt;/p&gt;</description>
    </item>
    <item>
      <title>MongoDB count могут сильно замедлить API</title>
      <link>https://www.alexkorablev.ru/dev/mongo-counters/</link>
      <pubDate>Fri, 23 Sep 2016 21:56:50 +0500</pubDate>
      <guid>https://www.alexkorablev.ru/dev/mongo-counters/</guid>
      <description>&lt;p&gt;Иногда команда фронтенда или другие потребители API просят выводить в эндпоинтах общее число объектов. Если в качестве хранилища используется MongoDB, постарайтесь избежать этого: такое поведение эндпоинтов может значительно их замедлить.&lt;/p&gt;
&lt;p&gt;Я говорю о тех случаях, когда ответ API похож на тот, что расположен ниже, — тогда ждите беды:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-json&#34; data-lang=&#34;json&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;total&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;XX&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;limit&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;ZZ&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;offset&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;YY&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;objects&amp;#34;&lt;/span&gt;: [&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;...&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Если коллекция достаточно большая, а запрос достаточно тяжёлый, &lt;code&gt;count&lt;/code&gt; будет работать непозволительно долго. Запрос &lt;code&gt;find&lt;/code&gt; при этом может работать быстро: ему ведь надо вернуть всего‑то десяток объектов. &lt;code&gt;count&lt;/code&gt; будет перебирать весь набор объектов, подходящих под условия запроса.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Не используйте dict так часто</title>
      <link>https://www.alexkorablev.ru/dev/dict-vs-object/</link>
      <pubDate>Fri, 09 Sep 2016 21:53:40 +0500</pubDate>
      <guid>https://www.alexkorablev.ru/dev/dict-vs-object/</guid>
      <description>&lt;p&gt;У разработчиков на Python наблюдается тенденция использовать словари (дикты) там, где нужно, и там, где нет. В основном это касается передачи данных внутри приложения в виде словаря (дикта), вместо создания объекта. Это плохой дизайн, который приводит к целому вороху проблем, самая страшная из которых — такой код невозможно читать.&lt;/p&gt;
&lt;p&gt;К примеру, есть код, который вызывает внешнее API и получает в ответ JSON, который уже распарсили в &lt;code&gt;dict&lt;/code&gt;. Стоит мне отправлять этот словарь дальше или лучше трансформировать его в экземпляр более специфического класса? Оба варианта возможны. Обычно я предпочитаю использовать классы и объекты, хотя это требует определённых усилий и времени: соответствующий класс надо ещё написать.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Переезд с Python на Java. Первые впечатления</title>
      <link>https://www.alexkorablev.ru/dev/java-vs-python/</link>
      <pubDate>Fri, 26 Aug 2016 22:18:14 +0500</pubDate>
      <guid>https://www.alexkorablev.ru/dev/java-vs-python/</guid>
      <description>&lt;p&gt;Буквально неделю назад я добавил Java в свой рабочий стек технологий: мы начали делать новый проект с использованием Java Spring Framework. Для меня это интересный вызов. Я никогда раньше не использовал Java, кроме как для маленьких домашних проектов. Вот мои самые первые впечатления о «лютом энтерпрайзе».&lt;/p&gt;
&lt;p&gt;Я не хочу сравнивать Python и Java как языки программирования. Очевидно, что в Java есть статическая типизация, а в Python — нет. Очевидно, что Java более многословна, а Python — более компактен. Всё это не так интересно. Гораздо интереснее сравнить окружение языков, требуемый ими подход к программированию.&lt;/p&gt;</description>
    </item>
    <item>
      <title>mypy для проекта на Python 2.7</title>
      <link>https://www.alexkorablev.ru/dev/mypy-python-27/</link>
      <pubDate>Fri, 29 Jul 2016 22:16:02 +0500</pubDate>
      <guid>https://www.alexkorablev.ru/dev/mypy-python-27/</guid>
      <description>&lt;p&gt;Аннотация типов может сильно помочь при работе над большим проектом на Python: многие ошибки в дизайне и использовании функций выявляются практически сразу. Конечно, для этого требуется использование внешних инструментов для статического анализа, таких как MyPy. Это великолепный инструмент, но он поддерживает третью ветку Python. Поддержка Python 2.7 в нём требует некоторой подготовки.&lt;/p&gt;
&lt;h2 id=&#34;type-comments-vs-stub-files&#34;&gt;Type comments vs stub files&lt;/h2&gt;
&lt;p&gt;Для начала нужно определиться, как аннотировать типы в коде. Для второй ветки Python есть два варианта: аннотирование в комментариях или использование стаб‑файлов. Я предпочитаю первый путь: он информативнее (типы перед глазами) и его легче поддерживать.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Свой итератор поверх enumerate</title>
      <link>https://www.alexkorablev.ru/dev/logging-iterator/</link>
      <pubDate>Mon, 27 Jun 2016 22:08:24 +0500</pubDate>
      <guid>https://www.alexkorablev.ru/dev/logging-iterator/</guid>
      <description>&lt;p&gt;ППару дней назад коллега попросил сделать логирующий сам себя итератор поверх &lt;code&gt;enumerate&lt;/code&gt;. Я попробовал наследоваться напрямую и потерпел неудачу. Я абсолютно забыл, как работает магический метод &lt;code&gt;__new__&lt;/code&gt;. Поскольку я был занят, я пообещал себе разобраться с этой проблемой позже. А ларчик открывался очень просто: 18 строк кода — и у меня появилась нужная функциональность.&lt;/p&gt;
&lt;h2 id=&#34;изначальная-задача&#34;&gt;Изначальная задача&lt;/h2&gt;
&lt;p&gt;Сначала стоит объяснить, зачем нам вообще понадобился подобный итератор и почему нам не хватило обычного &lt;code&gt;enumerate&lt;/code&gt;. Всё дело в том, что у нас в проекте очень много задач, построенных по такому шаблону:&lt;/p&gt;</description>
    </item>
    <item>
      <title>Онлайн курс по Clojure</title>
      <link>https://www.alexkorablev.ru/dev/clojure-mooc/</link>
      <pubDate>Tue, 07 Jun 2016 22:05:31 +0500</pubDate>
      <guid>https://www.alexkorablev.ru/dev/clojure-mooc/</guid>
      <description>&lt;p&gt;Clojure — интересный Lisp‑подобный функциональный язык. Если вы фанат круглых скобок, то программировать на этом языке интересно. К тому же Clojure компилируется в байт‑код JVM и транслируется в JavaScript. Вернее, в JS транслируется ClojureScript. Над ним работает та же команда, что и над Clojure, так что это всё‑таки один и тот же язык — за исключением некоторой разницы в типах и мелочах, зависящих от среды исполнения. При этом ресурсов для изучения этого языка не так много. Один из них — онлайн‑курс &lt;a href=&#34;http://iloveponies.github.io/120-hour-epic-sax-marathon/index.html&#34;&gt;Functional programming in Clojure&lt;/a&gt;.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Как управляться с большими проектами на Python</title>
      <link>https://www.alexkorablev.ru/dev/big-python-projects/</link>
      <pubDate>Wed, 01 Jun 2016 21:58:36 +0500</pubDate>
      <guid>https://www.alexkorablev.ru/dev/big-python-projects/</guid>
      <description>&lt;p&gt;На Hacker News появилась &lt;a href=&#34;https://news.ycombinator.com/item?id=11792474&#34;&gt;интересная дискуссия&lt;/a&gt; о том, как управляться с большими Python‑проектами. Поскольку я причастен к достаточно большому проекту, то не могу удержаться и не поделиться своим видением на этот вопрос. Я составил список из трёх моментов, на которые стоит обратить внимание.&lt;/p&gt;
&lt;h2 id=&#34;1-обеспечьте-себе-безболезненную-навигацию-по-коду&#34;&gt;1. Обеспечьте себе безболезненную навигацию по коду&lt;/h2&gt;
&lt;p&gt;В большом проекте навигация по коду и автокомплит сильно упрощают разработку и поддержку. Всё, что ломает навигацию, должно подвергаться сомнению. А это значит, что хитрые конструкции и метапрограммирование должны быть очень хорошо обоснованы: без них либо не обойтись, либо очень сложно обойтись. В остальных случаях лучше выбирать более очевидные (в том числе для тулзов) пути.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Проект на Kivy. Часть 1. Настройка окружения</title>
      <link>https://www.alexkorablev.ru/dev/setup-kivy-project/</link>
      <pubDate>Mon, 16 May 2016 21:52:27 +0500</pubDate>
      <guid>https://www.alexkorablev.ru/dev/setup-kivy-project/</guid>
      <description>&lt;p&gt;&lt;a href=&#34;https://kivy.org/#home&#34;&gt;Kivy&lt;/a&gt; — интересный проект, который позволяет делать кроссплатформенные GUI‑приложения, включая мобильные. Я решил выяснить, можно ли использовать его для создания маленьких приложений на Python. В этой серии статей я попробую исследовать Kivy на примере клона «конструктора слов» — одного из упражнений для LingvoLeo.&lt;/p&gt;
&lt;p&gt;Эта серия — не учебник, а исследовательский лог моих попыток. В результате я планирую получить собранные приложения для трёх платформ минимум: Windows, Mac, Android. Будет здорово, если я соберу ещё и iOS‑версию. В качестве основной платформы для разработки я использую Mac, так что все инструкции по установке и настройке окружения будут для этой операционной системы.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Модификация параметров под args или kwargs</title>
      <link>https://www.alexkorablev.ru/dev/args-kwargs/</link>
      <pubDate>Wed, 04 May 2016 16:48:57 +0500</pubDate>
      <guid>https://www.alexkorablev.ru/dev/args-kwargs/</guid>
      <description>&lt;p&gt;В Python достаточно часто интерфейсы функций частично или полностью «сворачивают» с помощью &lt;code&gt;*args&lt;/code&gt; и &lt;code&gt;**kwargs&lt;/code&gt;. Это вполне естественно для питонистов, но вызывает вопросы при переходе с других языков. С самим «сворачиванием» никаких проблем нет. Сложности возникают при модификации аргументов: строятся проверки вокруг &lt;code&gt;args&lt;/code&gt; и &lt;code&gt;kwargs&lt;/code&gt;, вместо того чтобы «развернуть» интерфейс функции.&lt;/p&gt;
&lt;p&gt;Представьте себе такой кейс: есть две библиотеки, одна из которых имеет полностью прописанный интерфейс у функции &lt;code&gt;foo&lt;/code&gt;. Вторая определяет функцию &lt;code&gt;boo&lt;/code&gt;, которая вызывает &lt;code&gt;foo&lt;/code&gt;. Интерфейс &lt;code&gt;boo&lt;/code&gt; «свёрнут» с помощью &lt;code&gt;*args&lt;/code&gt; и &lt;code&gt;**kwargs&lt;/code&gt;:&lt;/p&gt;</description>
    </item>
    <item>
      <title>Почему я вернулся в PyCharm</title>
      <link>https://www.alexkorablev.ru/dev/comeback-to-pycharm/</link>
      <pubDate>Mon, 18 Apr 2016 16:43:57 +0500</pubDate>
      <guid>https://www.alexkorablev.ru/dev/comeback-to-pycharm/</guid>
      <description>&lt;p&gt;В конце января я переключался на Sublime как основную IDE для Python. Но уже через пару недель я был вынужден вернуться на PyCharm. Последние несколько недель я активно использовал Emacs. Он великолепен. И всё‑таки для рабочих проектов я снова возвращаюсь к PyCharm.&lt;/p&gt;
&lt;p&gt;Все три варианта хорошо подходят для работы с Python. Все три позволяют работать продуктивно. Так что выбирать приходится исходя из слабых сторон каждого из них.&lt;/p&gt;
&lt;h2 id=&#34;что-не-так-с-pycharm&#34;&gt;Что не так с PyCharm&lt;/h2&gt;
&lt;p&gt;Есть несколько причин, почему я периодически пытаюсь сбежать в какой‑нибудь другой редактор.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Изменяемы типы в качестве параметров по умолчанию в Python</title>
      <link>https://www.alexkorablev.ru/dev/default-params/</link>
      <pubDate>Mon, 11 Apr 2016 16:41:04 +0500</pubDate>
      <guid>https://www.alexkorablev.ru/dev/default-params/</guid>
      <description>&lt;p&gt;Почему изменяемые типы не рекомендуется использовать в качестве значений аргументов по умолчанию в Python? Если вы забрались по карьерной лестнице выше джуниора, то наверняка задумывались. И наверняка ответ был таким: «Это приводит к странным побочным эффектам». Но я почти наверняка уверен, что только малая часть разработчиков на Python сделала шаг дальше и разобралась, почему такое поведение у языка.&lt;/p&gt;
&lt;p&gt;Давайте разберёмся сначала с тем, с какими побочными эффектами имеем дело. Напишем вот такую функцию:&lt;/p&gt;</description>
    </item>
    <item>
      <title>Обзор курса по Haskell на Stepic.org</title>
      <link>https://www.alexkorablev.ru/dev/stepic-haskell-mooc/</link>
      <pubDate>Mon, 04 Apr 2016 16:38:00 +0500</pubDate>
      <guid>https://www.alexkorablev.ru/dev/stepic-haskell-mooc/</guid>
      <description>&lt;p&gt;Как‑то я уже упоминал курс &lt;a href=&#34;https://stepic.org/course/%D0%A4%D1%83%D0%BD%D0%BA%D1%86%D0%B8%D0%BE%D0%BD%D0%B0%D0%BB%D1%8C%D0%BD%D0%BE%D0%B5-%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5-%D0%BD%D0%B0-%D1%8F%D0%B7%D1%8B%D0%BA%D0%B5-Haskell-75/syllabus&#34;&gt;«Функциональное программирование на языке Haskell»&lt;/a&gt;. Наконец могу поделиться собственными впечатлениями об этом курсе.&lt;/p&gt;
&lt;p&gt;Этот курс стоит того, чтобы его пройти и сделать (или хотя бы попытаться сделать) все предложенные задания. Лучшего вводного курса по Haskell я не встречал. Огромное спасибо Денису Москвину (основной преподаватель) и команде за курс!&lt;/p&gt;
&lt;p&gt;Курс состоит из 5 блоков, каждый из которых раскрывает некоторые аспекты языка: типы данных, списки, монады и т. п. Каждый блок — это набор видеоуроков с заданиями примерно на 5–6 часов работы.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Полезняшка: responses</title>
      <link>https://www.alexkorablev.ru/dev/responses/</link>
      <pubDate>Wed, 09 Mar 2016 18:30:51 +0500</pubDate>
      <guid>https://www.alexkorablev.ru/dev/responses/</guid>
      <description>&lt;p&gt;Если вы используете в своём проекте &lt;code&gt;requests&lt;/code&gt;, то наверняка сталкиваетесь с проблемами тестирования. На помощь придёт библиотека &lt;a href=&#34;https://github.com/getsentry/responses&#34;&gt;&lt;code&gt;responses&lt;/code&gt;&lt;/a&gt;, которая позволяет делать моки ответов вызовов &lt;code&gt;requests&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Мы в своём проекте используем эту библиотеку не так давно. Хотя из‑за особенностей окружения проекта мы часто обращаемся к огромному количеству REST API смежных сервисов. И до того, как &lt;code&gt;requests&lt;/code&gt; попалась нам на глаза, код тестов представлял из себя нечто невообразимое, трудночитаемое.&lt;/p&gt;
&lt;p&gt;Пользоваться библиотекой невероятно просто. Для иллюстрации — пара примеров из документации.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Generator vs Iterator</title>
      <link>https://www.alexkorablev.ru/dev/generator-vs-iterator/</link>
      <pubDate>Mon, 29 Feb 2016 18:29:21 +0500</pubDate>
      <guid>https://www.alexkorablev.ru/dev/generator-vs-iterator/</guid>
      <description>&lt;p&gt;Как ни странно, вопрос о разнице между генераторами и итераторами в Python — довольно частый. В общем‑то эти сущности сильно связаны (любой генератор — это итератор), их довольно часто путают, что иногда приводит к недопониманиям.&lt;/p&gt;
&lt;p&gt;Итератор — более общая концепция. Это объект, у которого определены два метода: &lt;code&gt;__next__&lt;/code&gt; и &lt;code&gt;__iter__&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;С другой стороны, генератор — это итератор, но не наоборот. Генератор может получаться с использованием &lt;code&gt;yield&lt;/code&gt; в теле функции:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;squares&lt;/span&gt;(start, stop):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; i &lt;span style=&#34;color:#f92672&#34;&gt;in&lt;/span&gt; range(start, stop):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;yield&lt;/span&gt; i &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; i
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;generator &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; squares(a, b)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Либо с использованием так называемых generator expression — например, такого:&lt;/p&gt;</description>
    </item>
    <item>
      <title>Как вы управляете своими pet-проектами?</title>
      <link>https://www.alexkorablev.ru/dev/pet-projects/</link>
      <pubDate>Tue, 16 Feb 2016 18:25:23 +0500</pubDate>
      <guid>https://www.alexkorablev.ru/dev/pet-projects/</guid>
      <description>&lt;p&gt;Сотни моих начинаний остаются недоделанными и даже близко не достигают целей, которые ставились перед проектом. И это при том, что зачастую основная цель — просто изучить ту или иную технологию.&lt;/p&gt;
&lt;p&gt;Самих идей проектов хоть отбавляй. Конечно, далеко не на всё есть время. Но самые «сочные» идеи хотелось бы реализовать — пусть не быстро, но хоть в какое‑нибудь разумное время.&lt;/p&gt;
&lt;p&gt;Из испробованных приёмов у меня более или менее нормально работает выделение времени по утрам. Причём работает где‑то половину года, когда светает достаточно рано. Заставить себя выбраться из‑под одеяла зимой — дохлый номер. Не помогает и какой‑нибудь ритуал, который хорошо работает летом. Обычно всё скатывается к просмотру какого‑нибудь сериала лёжа в кровати.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Страсть к смене технологий: с Python на Lua</title>
      <link>https://www.alexkorablev.ru/dev/from-python-to-lua/</link>
      <pubDate>Mon, 08 Feb 2016 18:23:14 +0500</pubDate>
      <guid>https://www.alexkorablev.ru/dev/from-python-to-lua/</guid>
      <description>&lt;p&gt;Брайан Майер из Distelli опубликовал любопытную статью &lt;a href=&#34;https://www.distelli.com/blog/using-lua-for-our-most-critical-production-code&#34;&gt;«Using Lua for Our Most Critical Production Code»&lt;/a&gt;. В статье расхваливается переход с одной технологии на другую и то, как это помогло решить кучу проблем. При этом совсем не упоминается, с какими проблемами при этом столкнулись, и совсем нет анализа, какие проблемы могут возникнуть в будущем.&lt;/p&gt;
&lt;p&gt;По большому счёту, смена технологии проекта в его середине — обычно очень плохая идея. Программистов надо вытащить из области, в которой они разбираются, в совершенно незнакомое окружение. Не могу сказать, что это всегда негативно сказывается на команде, но такие риски надо просчитывать. Если человека нанимали за его экспертные знания в Python, будет ли он счастлив писать на Lua?&lt;/p&gt;</description>
    </item>
    <item>
      <title>В чем главная слабость Python, как языка программирования?</title>
      <link>https://www.alexkorablev.ru/dev/python-weaknesses/</link>
      <pubDate>Mon, 25 Jan 2016 22:18:28 +0500</pubDate>
      <guid>https://www.alexkorablev.ru/dev/python-weaknesses/</guid>
      <description>&lt;p&gt;Я очень люблю Quora.com. В отличие от Stack Overflow, здесь можно найти интересные обсуждения, не связанные с конкретными вопросами, а с общими ощущениями от технологий. Недавно наткнулся, к примеру, на такое обсуждение: &lt;a href=&#34;https://www.quora.com/What-are-the-main-weaknesses-of-Python-as-a-programming-language&#34;&gt;«What are the main weaknesses of Python as a programming language?»&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;В основном Python ругают за тормознутость, сравнивая с компилируемыми языками. Я уже &lt;a href=&#34;https://www.alexkorablev.ru/dev/why-python-so-popular/&#34;&gt;писал&lt;/a&gt;, что считаю это обвинение надуманным. Для меня скорость разработки гораздо важнее. Для CPU‑bound задач я бы в первую очередь подумал об алгоритмах, а потом использовал Cython. Да и не так уж много таких задач. А если ваш проект весь такой, то какого лешего вы выбрали скриптовый язык для этого?&lt;/p&gt;</description>
    </item>
    <item>
      <title>Приватных полей в питоне нет</title>
      <link>https://www.alexkorablev.ru/dev/pivate-variable/</link>
      <pubDate>Mon, 18 Jan 2016 21:45:05 +0500</pubDate>
      <guid>https://www.alexkorablev.ru/dev/pivate-variable/</guid>
      <description>&lt;p&gt;Достаточно часто встречаю вопросы о приватных полях и методах в Python от людей, которые раньше программировали на Java (или C++). Вот только в Python класс — это не совсем то же, что и в Java. В Python класс — это просто контейнер, содержимое которого доступно всем.&lt;/p&gt;
&lt;p&gt;«Приватные» поля — это всего лишь договорённость по именам, которая никак не мешает работать с такими полями из любого места кода. Добавление имени класса к имени переменной — слабая защита.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Я влюбился в Django. Снова. А вы что сделали за новогодние каникулы?</title>
      <link>https://www.alexkorablev.ru/dev/fall-in-love-with-django/</link>
      <pubDate>Mon, 11 Jan 2016 21:43:06 +0500</pubDate>
      <guid>https://www.alexkorablev.ru/dev/fall-in-love-with-django/</guid>
      <description>&lt;p&gt;Ещё 31 декабря прошлого года у меня были гигантские планы на каникулы. Как минимум я должен был закончить один из своих сайт‑проектов. К сожалению, работе удалось уделить всего 4 часа. Но за это время я успел снова влюбиться в Django.&lt;/p&gt;
&lt;p&gt;Кажется, я где‑то уже об этом писал: Django — это мой проводник в мир Python. Именно благодаря этому фреймворку меня вырвало из хищных лап PHP. И первое время к Python я относился как к досадной необходимости, без которой Django не работает.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Django или Flask?</title>
      <link>https://www.alexkorablev.ru/dev/django-vs-flask/</link>
      <pubDate>Mon, 28 Dec 2015 18:31:44 +0500</pubDate>
      <guid>https://www.alexkorablev.ru/dev/django-vs-flask/</guid>
      <description>&lt;p&gt;Решил восстановить свой сайт о настольных играх — VseNastolki.ru. Когда‑то там был интернет‑магазин, но, поскольку теперь на столь серьёзный проект меня не хватит, я буду делать всего лишь базу настольных игр. Оформив идею, я, как настоящий программист, взялся за выбор фреймворка: Flask или Django.&lt;/p&gt;
&lt;p&gt;Другие фреймворки я не рассматривал. Причина проста: у меня нет опыта работы с ними. Проект хочется закончить, так что использовать неизвестный фреймворк для этого не хочется. Так что в кандидатах остались только Flask — наш текущий фреймворк на работе — и Django — фреймворк, из‑за которого я попал в мир Python.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Деление данных по коллекциям в MongoDB</title>
      <link>https://www.alexkorablev.ru/dev/mongo/</link>
      <pubDate>Mon, 21 Dec 2015 18:28:04 +0500</pubDate>
      <guid>https://www.alexkorablev.ru/dev/mongo/</guid>
      <description>&lt;p&gt;Не надо лезть в MongoDB с реляционным подходом. Этот тезис вроде бы очевиден, но когда дело доходит до реализации, возникает множество вопросов. И стопроцентно одним из них будет: «Как делать join?». Правильный ответ: никак.&lt;/p&gt;
&lt;p&gt;Да, в версии 3.2 появился &lt;code&gt;$lookup&lt;/code&gt; в агрегациях. Отчасти это замена классическому &lt;code&gt;JOIN&lt;/code&gt; из реляционного мира. Но в целом агрегации — не самый быстрый в MongoDB инструмент. Лучше, когда запрос идёт к одной коллекции и это обычный &lt;code&gt;find&lt;/code&gt;.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Почему Python такой популярный, если он такой медленный?</title>
      <link>https://www.alexkorablev.ru/dev/why-python-so-popular/</link>
      <pubDate>Mon, 14 Dec 2015 18:25:43 +0500</pubDate>
      <guid>https://www.alexkorablev.ru/dev/why-python-so-popular/</guid>
      <description>&lt;p&gt;На Quora обсуждают &lt;a href=&#34;https://www.quora.com/Why-is-Python-so-popular-despite-being-so-slow&#34;&gt;«Почему Python такой популярный, хотя такой медленный»&lt;/a&gt;. Тема, конечно, холиварная. Но порассуждать на неё интересно. Ведь Python действительно медленный.&lt;/p&gt;
&lt;p&gt;Медленный, если сравнивать его с C/C++, Java или C#. Это факт. Python — достаточно медленный скриптовый динамический язык программирования. Любая метрика покажет, что программа на C++ будет работать быстрее. Но есть у языков и другая, не менее важная метрика — скорость разработки.&lt;/p&gt;
&lt;p&gt;Вот тут динамические языки начинают выигрывать. Разрабатывать на Python, Ruby, JS быстрее, чем на Java. А скорость разработки — это прямая экономия для компании. Сегодня разработка продукта заканчивается, только если проект закрывают. В остальных случаях купить ещё один инстанс у Amazon дешевле, чем увеличить срок разработки какой‑либо фичи на пару недель.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Sublime Text 3 как Python IDE</title>
      <link>https://www.alexkorablev.ru/dev/python-ide/</link>
      <pubDate>Mon, 07 Dec 2015 18:15:51 +0500</pubDate>
      <guid>https://www.alexkorablev.ru/dev/python-ide/</guid>
      <description>&lt;p&gt;Пока на RealPython разжигают войну IDE и объясняют, как настроить среду разработки на Python под:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://realpython.com/blog/python/setting-up-sublime-text-3-for-full-stack-python-development/&#34;&gt;Sublime&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://realpython.com/blog/python/vim-and-python-a-match-made-in-heaven/&#34;&gt;VIM&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://realpython.com/blog/python/emacs-the-best-python-editor/&#34;&gt;Emacs&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Я расскажу, почему я (пока) переехал на Sublime Text 3 и как я его настроил. А также отмечу, чего в нём не хватает для счастливой разработки.&lt;/p&gt;
&lt;p&gt;PyCharm — замечательная IDE для Python. Это, несомненно, так, но если нужно разрабатывать full‑stack, то одним им не обойтись. На работе это не проблема. Но вот дома покупать лицензию на все продукты JetBrains ради экспериментов накладно.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Flask: что почитать</title>
      <link>https://www.alexkorablev.ru/dev/flask-reading-list/</link>
      <pubDate>Mon, 30 Nov 2015 13:58:48 +0500</pubDate>
      <guid>https://www.alexkorablev.ru/dev/flask-reading-list/</guid>
      <description>&lt;p&gt;&lt;strong&gt;НЕ! Обновляемый список полезных ссылок с материалами по Flask&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Версия: 1.0. Последнее обновление: 30.11.2015.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Начинающим&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;http://blog.miguelgrinberg.com/post/the-flask-mega-tutorial-part-i-hello-world&#34;&gt;«The Flask Mega‑Tutorial»&lt;/a&gt; — подробный пошаговый учебник по веб‑фреймворку Flask. Покрывает все основные темы: шаблоны, формы, базу данных, интернационализацию, деплоймент на сервере.&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://youtu.be/DIcpEg77gdE&#34;&gt;«Flask Workshop»&lt;/a&gt; — трёхчасовое видео от того же автора. Демонстрация основных возможностей Flask на живом примере.&lt;/li&gt;
&lt;li&gt;Ещё один учебник — &lt;a href=&#34;http://simplectic.com/blog/2014/flask-todomvc-part1/&#34;&gt;«Flask TodoMVC»&lt;/a&gt;. На этот раз создают не блог, а список задач (To‑Do). Плюс этого учебника в том, что рассматривается не только Flask, но и его использование в связке с JS‑фреймворком &lt;a href=&#34;http://backbonejs.org/&#34;&gt;Backbone.js&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://realpython.com/blog/python/flask-by-example-part-1-project-setup/&#34;&gt;«Flask by Example»&lt;/a&gt; — учебный пример с Flask, Redis и Angular.&lt;/li&gt;
&lt;li&gt;Если ещё не устали от учебников и учебных проектов, посмотрите ещё один материал от Real Python — &lt;a href=&#34;https://realpython.com/blog/python/python-web-applications-with-flask-part-i/&#34;&gt;«Python Web Applications With Flask»&lt;/a&gt;. Помимо того, что это хороший, подробный и понятный учебник, в нём описывается переход от небольшого приложения к среднему — во Flask это нетривиальная задача. В &lt;a href=&#34;https://realpython.com/blog/python/python-web-applications-with-flask-part-iii/&#34;&gt;третьей части&lt;/a&gt; рассматриваются вопросы тестирования и отладки приложения.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Опытным пользователям&lt;/strong&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>Конвертирование андроид приложения на Kotlin</title>
      <link>https://www.alexkorablev.ru/dev/converting-plaid-to-kotlin/</link>
      <pubDate>Mon, 16 Nov 2015 13:54:25 +0500</pubDate>
      <guid>https://www.alexkorablev.ru/dev/converting-plaid-to-kotlin/</guid>
      <description>&lt;p&gt;На прошлой неделе наткнулся на очень интересную статью от Антонио Лева: &lt;a href=&#34;http://antonioleiva.com/plaid-kotlin-1&#34;&gt;«Converting Plaid to Kotlin: Lessons Learned»&lt;/a&gt;. В ней автор на примере одного Android‑приложения сравнивает Kotlin и Java. Цель — выявить преимущества и недостатки разработки на Kotlin.&lt;/p&gt;
&lt;p&gt;Если посмотреть на числа, которые приводит автор, то по ним видно, что на Kotlin код получается значительно компактнее: на 22 % меньше строк, на 27 % меньше символов. Это значит, что программировать на Kotlin значительно быстрее, чем на Java. Да и приятнее (но это цифрами не измерить).&lt;/p&gt;</description>
    </item>
    <item>
      <title>Highload&#43;&#43; 2015</title>
      <link>https://www.alexkorablev.ru/dev/highload-2015/</link>
      <pubDate>Wed, 11 Nov 2015 13:48:28 +0500</pubDate>
      <guid>https://www.alexkorablev.ru/dev/highload-2015/</guid>
      <description>&lt;p&gt;На прошлой неделе прошла конференция Highload++ 2015. Конференция большая: доклады шли в 5 потоков. Казалось бы, выбор большой, но если отбросить секцию менеджмента и секцию фронтенд‑разработки, то в каждом втором докладе будет PostgreSQL. Один из моих коллег так высказался о конференции: «Highload++ 2015 — 40 % PostgreSQL, 40 % очереди, 20 % приправы».&lt;/p&gt;
&lt;p&gt;Не буду рассказывать о всех докладах, которые я посетил. Как и на всякой конференции, было много неудачных докладов. Я расскажу немного о трёх, на мой взгляд, самых достойных докладах конференции. Если будете покупать видео с этой конференции, то записи первых двух докладов стоят того, чтобы их посмотреть. Про третий доклад разговор отдельный.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Cpython Internals Walk Through</title>
      <link>https://www.alexkorablev.ru/dev/cpython-internals-walk-through/</link>
      <pubDate>Mon, 02 Nov 2015 13:45:31 +0500</pubDate>
      <guid>https://www.alexkorablev.ru/dev/cpython-internals-walk-through/</guid>
      <description>&lt;p&gt;Ресурсов о том, как работает стандартная реализация Python (CPython) внутри, мало. Пробиваться самому сквозь не самый очевидный код на C — задача для питониста очень сложная. Чтение кода на C требует определённой практики. &lt;a href=&#34;https://www.youtube.com/embed/videoseries?list=PLwyG5wA5gIzgTFj5KgJJ15lxq5Cv6lo_0&#34;&gt;Серия лекций&lt;/a&gt;, прочитанная Филипом Гио, — хорошая отправная точка.&lt;/p&gt;
&lt;p&gt;Филип подробно рассказывает о внутренних структурах Python, проводя студентов от байт‑кода к структурам, написанным на C.&lt;/p&gt;
&lt;p&gt;Темы, охваченные курсом:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Байт‑код и главный цикл интерпретатора.&lt;/li&gt;
&lt;li&gt;Фреймы, вызовы функций, области видимости.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;PyObject&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Типы данных в Python.&lt;/li&gt;
&lt;li&gt;Объект с кодом, объект функции.&lt;/li&gt;
&lt;li&gt;Итераторы.&lt;/li&gt;
&lt;li&gt;Классы и объекты.&lt;/li&gt;
&lt;li&gt;Генераторы.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Рассказ ведётся с большим количеством примеров. Каждое погружение внутрь Python начинается с конкретного кусочка кода на Python. Потом разбирается получившийся байт‑код. Дальше — уже команда за командой — разбирается реализация команд байт‑кода на C.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Самые слабые стороны программистов-самоучек</title>
      <link>https://www.alexkorablev.ru/dev/self-taught-programmers-lack/</link>
      <pubDate>Mon, 26 Oct 2015 21:46:24 +0500</pubDate>
      <guid>https://www.alexkorablev.ru/dev/self-taught-programmers-lack/</guid>
      <description>&lt;p&gt;Меня огорчает реакция людей, когда на вопрос «Как мне стать хорошим программистом?» советуешь прочитать книгу по алгоритмам. Хорошо, если каждый десятый спрашивает, какую я посоветую. Остальные девять говорят, что им это не нужно. А ведь алгоритмы — это лишь одна из многих проблем у программистов‑самоучек.&lt;/p&gt;
&lt;p&gt;Я это очень хорошо знаю: я сам из самоучек. У меня план по закрытию пробелов в знаниях расписан года на два вперёд. Так что я провожу на Coursera по 3–4 часа в неделю, только чтобы добрать базу. А ведь надо ещё и новые технологии изучать, и работать с хорошей эффективностью. И я считаю, что мне ещё повезло: моих знаний в математике пока хватает.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Kotlin - мой следующий JVM-язык</title>
      <link>https://www.alexkorablev.ru/dev/kotlin/</link>
      <pubDate>Mon, 19 Oct 2015 21:42:27 +0500</pubDate>
      <guid>https://www.alexkorablev.ru/dev/kotlin/</guid>
      <description>&lt;p&gt;Утром, в дополнение к физическим упражнениям, я примерно час программирую. Для этого отлично подходят не очень сложные проекты, которые делаются в кайф. Для меня это маленькие игры и приложения для Android. Первый подобный проект я написал на Java. Второй стартовал так же — на Java. Но я решил его портировать на Kotlin.&lt;/p&gt;
&lt;p&gt;Основная проблема Java — её многословность. Проект очень быстро перестал «влазить» в голову, особенно по утрам. Обычно это означает, что пришло время рефакторинга и код придётся дробить, делать его похожим на «лютый энтерпрайз». Тоска. А так как проект делается для удовольствия, то я решил попробовать что‑нибудь новенькое и поменять язык разработки.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Паттерн Singleton</title>
      <link>https://www.alexkorablev.ru/dev/singleton/</link>
      <pubDate>Mon, 12 Oct 2015 10:00:00 +0500</pubDate>
      <guid>https://www.alexkorablev.ru/dev/singleton/</guid>
      <description>&lt;p&gt;&lt;code&gt;lambda&lt;/code&gt; не так часто встречается в коде на Python. Есть большая вероятность, что если потребовался синглтон, то в проекте есть проблемы с архитектурой. В первую очередь это касается небольших и средних проектов. Да и в больших проектах синглтон в чистом виде встретишь нечасто.&lt;/p&gt;
&lt;p&gt;Когда я готовился к этой статье, я планировал написать о вариантах реализации паттерна. Но когда я начал исследовать, первым делом я наткнулся на следующий код в Википедии:&lt;/p&gt;</description>
    </item>
    <item>
      <title>Неплохой вводный видео-курс по Python</title>
      <link>https://www.alexkorablev.ru/dev/python-video-course/</link>
      <pubDate>Mon, 28 Sep 2015 10:00:40 +0500</pubDate>
      <guid>https://www.alexkorablev.ru/dev/python-video-course/</guid>
      <description>&lt;p&gt;Люблю смотреть разные видеокурсы по используемым языкам и технологиям. Причём не только по продвинутым темам, но и по базовым. Ещё не было такого курса, в котором не нашлось бы чего‑нибудь интересного и полезного для меня.&lt;/p&gt;
&lt;p&gt;О последнем просмотренном мной &lt;a href=&#34;https://www.youtube.com/embed/videoseries?list=PLPErILqzuTQr7QJ4rAFJVvzdTEFFPjaGz&#34;&gt;курсе&lt;/a&gt; от Георгия Курячего я хочу немного рассказать. Этот курс — отличное базовое введение в Python 2.&lt;/p&gt;
&lt;p&gt;Возможно, если вы изучали Python в университете, то этот курс покажется вам слабоватым. Но мне, как человеку, который изучал язык и его библиотеку разрозненно — по книгам, статьям и отдельным видео, — такой курс показался вполне достойным. Он полностью оправдал время, потраченное на него.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Итоги конференции PyConRu 2015</title>
      <link>https://www.alexkorablev.ru/dev/pyconru-2015/</link>
      <pubDate>Mon, 21 Sep 2015 10:00:12 +0500</pubDate>
      <guid>https://www.alexkorablev.ru/dev/pyconru-2015/</guid>
      <description>&lt;p&gt;В субботу закончилась конференция PyCon Ru 2015 в Екатеринбурге. Немного остыв, можно подвести некоторые итоги. Конференция получилась хорошей. Как говорит один мой коллега, если на двухдневной конференции было два интересных доклада, то конференция удалась. На PyCon интересных и полезных докладов было больше. Я выделил 4 таких доклада.&lt;/p&gt;
&lt;p&gt;Начало положил Гаель Вароко. Если про &lt;a href=&#34;http://scikit-learn.org/stable/&#34;&gt;&lt;code&gt;scikit&lt;/code&gt;&lt;/a&gt; было просто интересно послушать — в повседневной работе мы машинным обучением не занимаемся, — то рассказ о второй библиотеке &lt;a href=&#34;http://pythonhosted.org/joblib/&#34;&gt;&lt;code&gt;joblib&lt;/code&gt;&lt;/a&gt; заставил нас провести порядочное время на её сайте. Сама библиотека позволяет легко организовывать параллельные вычисления. И нам был очень интересен ответ на вопрос, сможем ли мы её использовать в своём проекте.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Почему не я люблю декораторы и метаклассы</title>
      <link>https://www.alexkorablev.ru/dev/why-i-hate-metaclasses/</link>
      <pubDate>Mon, 14 Sep 2015 10:00:10 +0500</pubDate>
      <guid>https://www.alexkorablev.ru/dev/why-i-hate-metaclasses/</guid>
      <description>&lt;p&gt;Я не люблю декораторы и метаклассы. Почти любое использование декоратора и любое использование метакласса ухудшает читаемость кода. Их трудно использовать без усложнения кода. Они приводят к трудновыявляемым багам. Так что их использование должно быть обосновано. И их не нужно использовать там, где можно легко и безболезненно обойтись без них.&lt;/p&gt;
&lt;p&gt;Если сравнить использование остальных конструкций языка с использованием рогатки, то использование декоратора — это стрельба из пушки, а метаклассы — из системы залпового огня «Град». Последствия их неправильного использования влияют на кодовую базу примерно так же. Декоратор «разламывает» несколько функций и методов, метакласс «разрывает в клочья» несколько классов.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Type Hinting в Python 3.5</title>
      <link>https://www.alexkorablev.ru/dev/type-hinting/</link>
      <pubDate>Mon, 31 Aug 2015 10:00:26 +0500</pubDate>
      <guid>https://www.alexkorablev.ru/dev/type-hinting/</guid>
      <description>&lt;p&gt;«Утиная» типизация, конечно, ускоряет написание программ, но только до определённых пределов. В больших проектах, когда количество кода достаточно велико, такая гибкость начинает давать сбои. С Python 3.0 можно делать типизацию для функций. Но только с 3.5 появится действительно мощный инструмент, встроенный в язык.&lt;/p&gt;
&lt;p&gt;Конечно, можно делать описание параметров и возвращаемых значений в докстрингах. Вот только кто их пишет? А если пишет, то кто следит за их актуальностью? Программисты ленивы: если можно что‑то не делать, они не будут этого делать.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Кастомные коллекции</title>
      <link>https://www.alexkorablev.ru/dev/magic-methods-getitem/</link>
      <pubDate>Mon, 24 Aug 2015 10:00:36 +0500</pubDate>
      <guid>https://www.alexkorablev.ru/dev/magic-methods-getitem/</guid>
      <description>&lt;p&gt;Хорошо написанный код на Python должен работать с последовательностями однообразно. При этом неважно, встроенные это последовательности или нет. Тем более что свою последовательность написать в Python очень просто. Нужно всего лишь переопределить &lt;code&gt;__len__&lt;/code&gt; и &lt;code&gt;__getitem__&lt;/code&gt;, чтобы работа с вашей последовательностью в большинстве случаев не отличалась от работы со встроенными последовательностями.&lt;/p&gt;
&lt;p&gt;В качестве иллюстрации возьмём такой пример. У нас есть класс &lt;code&gt;ShoppingBasket&lt;/code&gt;. В нём лежат какие‑то товары. Пусть нам нужно пройтись по всем товарам, научиться получать товары по ключу и добавлять товары.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Celery: Pickle от которого невозможно отказаться</title>
      <link>https://www.alexkorablev.ru/dev/celery-pickle-ot-kotorogo-nevozmozhno-otkazatsya/</link>
      <pubDate>Mon, 10 Aug 2015 11:00:00 +0500</pubDate>
      <guid>https://www.alexkorablev.ru/dev/celery-pickle-ot-kotorogo-nevozmozhno-otkazatsya/</guid>
      <description>&lt;p&gt;Если вы решили поменять сериализатор задач для Celery с Pickle на какой‑нибудь другой, ничего не выйдет. Вернее, задачи действительно будут сериализоваться и десериализоваться с помощью указанного сериализатора. Но внутри Celery всё равно используется Pickle, и это никак не изменить. Вернее, не в Celery, а в библиотеке &lt;code&gt;billiard&lt;/code&gt;, которая используется мастер‑процессом воркера для раздачи задач из очереди подпроцессам.&lt;/p&gt;
&lt;p&gt;В нашем проекте мы столкнулись с тем, что иногда передаём в качестве параметра задач Celery &lt;code&gt;NoneType&lt;/code&gt;. Причём не значение &lt;code&gt;None&lt;/code&gt;, а именно &lt;code&gt;NoneType&lt;/code&gt;.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Декораторы с параметрами по умолчанию</title>
      <link>https://www.alexkorablev.ru/dev/dekoratory-s-parametrami-po-umolchaniyu/</link>
      <pubDate>Mon, 03 Aug 2015 13:19:00 +0500</pubDate>
      <guid>https://www.alexkorablev.ru/dev/dekoratory-s-parametrami-po-umolchaniyu/</guid>
      <description>&lt;p&gt;Декораторы в Python — удобный инструмент. Если ими пользоваться с умом, они значительно повышают читаемость кода и его повторное использование.&lt;/p&gt;
&lt;p&gt;Но есть один момент, который меня немного напрягает: для декоратора с параметрами по умолчанию нужно ставить пустые круглые скобки после его вызова. Время от времени это приводит к ошибкам. Особенно это актуально, если декоратор является частью публичного API.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;@decorator_wo_params&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;f1&lt;/span&gt;():
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;pass&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;@decorator_w_defaults_params&lt;/span&gt;()  &lt;span style=&#34;color:#75715e&#34;&gt;# Ну зачем здесь пустые скобки?&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;f2&lt;/span&gt;():
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;pass&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;С этим можно смириться. В режиме жёстких сроков и большого потока задач времени на поиск решения, написание и тестирование дополнительного кода может просто не быть. Нормальное тестирование выявит проблему моментально. Но иногда невозможно удержаться и не сделать свой код немного красивее.&lt;/p&gt;</description>
    </item>
  </channel>
</rss>
