код в одну строку python

Непрактичный python — пишем декоратор в одну строку

Давеча с коллегой на работе поспорили, что нельзя написать кэширующий декоратор в 4 строки. Я утверждал, что можно. Все началось с 4-х строк, закончилось функциональным программированием кучей lambda выражений в одну строку и декоратором в одну строку.

Дисклеймер

Такой код не попадает в мои проекты или проекты моей команды, и все что описано ниже было написано в рамках академического изыскания. Я понимаю что важное преимущество python в его читабельности. Автором, из изменяющих сознания вещества, при написании данного поста, было использовано только кофе.

Пролог

Идея написать декоратор в 4 строки меня изначально никак не трогала. Было просто интересно написать декоратор. Но в процессе спортивный интерес взял верх. Изначально все начиналось с простого кэширующего декоратора.

Сейчас задача из 18 строк кода, 11 если удалить пробелы и комментарии, сделать 4 строки. Первое что приходит на ум, записать конструкцию if…else в одну строчку.

Теперь у нас 15 строк кода против 18, и появился ещё один if, что создает дополнительную вычислительную нагрузку, но сегодня мы собрались не для улучшению performance. Давайте добавим в этот мир энтропии и немного copy-paste и упростим переменную key.

Теперь мы имеем 12 строк, без пробелов и комментариев 8 строк. Нам пока этого не достаточно, цель 4 строчки, и надо упростить ещё. Мы помним что декоратор — это функция которая должна возвращать callable объект (функцию). Функцией может быть и lambda! Значит мы можем упростить и функцию wrapper и заменить её на lambda — анонимную функцию. И возвращать из функции «декоратора», анонимную функцию.

Цель достигнута! Декоратор в 4 строки, чистого кода — получился. Как можно увидеть одной lambda функцией не обошлось, пришлось создать две lambda функции. Первая lambda делает две вещи: если объект уже был закешировав возвращаем ранее закешировнанное значение и кэширует объект если он не был ранее кэширован но в таком случае мы нечего не возвращаем.

Первая lambda функция теперь у нас не анонимная её пришлось записать в переменную чтобы к ней можно было обращаться по имени переменной. Вторая lambda делает примерно тоже самое что и первая только обращалась к первой lambda по имени, кеширует и получает значения из кеша, в случае если первая lambda не вернула значение, значит объект новый и он был закэширован и значит вторая lambda вернет входящие значение.

Конструкция получилась громоздкой, но все равно читаемая, более или менее — при условии если вы легко читаете lambda выражения. Много условностей, но это ещё не ад но мы к нему приближаемся. После всего проделанного пути все ещё кажется что можно ещё сократить количество строк кода. Мы уже вошли во вкус. Например те-же две lambda выражения можно совместить в одно выражение. Давайте объединим две lambda функции в одну.

Для этого нам надо пойти на некоторое ухищрение, использовать тернарный оператор or. Тернарный оператор принимает два значения, справа и слева относительно себя, и пытается получить логический ответ True или False. Как оператор сравнения. Для того чтобы вычислить конструкцию слева и справа интерпретатор python выполнит код справа и слева. Слева у нас конструкция memory.update(