Комментарии 26
В этой статье я покажу изящный прием, который превратит ваши многоэтажные условия в плоский, легко расширяемый и тестируемый код. Всего за 5 минут вы научитесь писать код, который коллеги будут показывать как пример для подражания.
Немного примеров match/case в Python 3.10
Существует уже 4 года. Не благодарите.
Меня зовут Михаил, я веду Telegram-канал «Python Шпильки», где делюсь изящными приемами программирования.
Спасибо, запомнил. Ни в коем случае не подписываться.
Немного примеров match/case в Python 3.10
Существует уже 4 года. Не благодарите.
А если у меня проект для 2.7 Пайтона, будет ли резонно использовать этот метод, вместо въевшегося if-else?
А если у меня не python 2.7, а проект на перфо картах?
А если на Cobol? Короче говоря, если вы поддерживаете проект на python 2, поддержка которого прекратилась в 2020 и который сейчас не поставляется в дистрибутивах, то вы достаточно опытный разработчик, чтобы вручную возиться со всем этим старьём и вам не нужны такие советы, сами способны додуматься.
А вот показывать такое новичкам как "изящные решения для повседневных задач разработчика", пожалуйста, не надо.
Решение на основе словаря можно динамически изменить или расширить, в этом его преимущество. Впрочем, это не часто требуется.
Очень много синтаксического мусора в виде низачем не нужных имён методов из-за отсутствия в питоне многострочных лямбд.
Когда не знал про паттерн "стратегия", но умеешь пользоваться LLM и генерировать ИИ-шит
то, что он класс не назвал Strategy, не означает, что он не реализовал данный паттерн лол))
у автора как раз таки и реализован паттерн стратегия, с некоторыми нюансами, но все же, для примера вполне достаточно.
есть хендлеры, есть условия, при которых выбирается нужный хендлер, есть дешевый мапинг. единственное, я бы сделал это в виде отдельных классов и не привязывался к классу OrderProceccor, тем самым создав пространство для масштабирования.
с чем вы тут не согласны?)))
Мне не нравится тем, что это AI-slop и LLM-shit
Но если предположить, что публикатор все же писал статью "вручную"...
Если ты пишешь тег "Паттерны проектирования" - то сошлись, что в этих самых паттернах такой подход называется стратегией.
Вообще, многие разработчики на питоне имеют какую-то антипатию к патернам, аппелируя к тому, что паттерны переусложнены и в них много лишнего - вот смотрите, как можно просто сделать, "тяп-ляп и в продакшн". В результате получается то, что получается - код, насквозь прошитый глобальными переменными, статическими сессиями и глобальными функциями с сайд-эффектами. Да-да, весь этот ад с reserve_inventory(...) - откуда у нее возьмется сессия, в которой она сходит в базу или другой микросервис? Или notify_customer_service(...) - откуда в нем возьмутся реквизиты для доступа к очередям рассылки уведомлений?
Такие простые реализации, которые смело копипастит из ответов LLM автор - без всей этой замученности с типами, классами и прочим - они в рабочей схеме не прокатят. Код хорошо бы прогонять через проверку статической типизации - вот эти вот все from typing import .... и mypy (это вообще категорическое требование - с моей точки зрения, код без них вообще недопустим, кроме случаев безжалостного легаси). А когда привозится статическая типизация, вот тогда и начинается самое интересное - то есть то, чего начинающие разработчики не любят.
Ну а то, что показано в статье - поытка разделить god method - но в результате просто превращает его в god object. Но LLM на это пофиг, чушь на входе - чушь на выходе, обучили на спагетти из статиков, глобальных переменных и сайдэффектов - получите то же самое в ответ на свой запрос. И следующую итерацию обучат на этом же генеративе. Идеальная самоодебиливающаяся система, которая учится быть еще тупее на своем же выхлопе.
согласен с тем, что большинство разработчиков на питоне забивают на паттерны. просто сам язык позволяет не углубляться в эти знания и шлепать как попало
Вообще, многие разработчики на питоне имеют какую-то антипатию к патернам, аппелируя к тому, что паттерны переусложнены и в них много лишнего - вот смотрите, как можно просто сделать, "тяп-ляп и в продакшн".
Просто в нашей любимой замке паттерны буквально переусложненны. Недавно неплохая статья была на хабре, что-то вроде "Почему паттерны проектирования в питоне не работают". Очень интересная статья которая очень точно описывает часть нюансов отношения змеи и паттернов.
Общий посыл статьи примерно такой - "Зачем шаблоны, если можно и лучше без шаблонов". То что указанное в статье является каким то шаблоном вообще удивление. В некоторых случаях в питоне можно callable метать и по спискам, и интегрироваться по ним. И использовать как замыкания.
Шаблон это подход, принцип реализации задачи. Детали могут отличаться, но суть одна и та же - создается посредник, в котором регистрируются исполнители (стратегии). Принятие решения о том какому исполнителю выполнить действие (какую стратегию использовать) принимает посредник. Вместо прямого вызова исполнителя вызывается посредник.
И далее начинаются уже детали реализации, например будут ли посредники Callable (питон), делегатами (C#) или объектами реализующими интерфейс (Java), будет ли выбор реального актора базироваться на словаре, или стратегии будут предоставлять предикаты которые определяют готовность стратегии обработать вызов, или какой-нибудь другой способ. Много вариантов.
То, что автор не любит слово "шаблон" не значит, что его тут нет :-)
В случае чуть более-менее сложных логик, описываемый подход (с использованием словаря обработчиков, где значения - обработчики, а ключи - строки воходных логических параметров) все равно значительно лучше, чем как match/case, так и паттерна стратегия, ИМХО. Таким подходом еще деды на ассемблере пользовались. Он прост и надежен, как АК-47.
Если есть обоснованное предположение, что структура функций не будет меняться, либо более сложная логика появится только в редких статус-обработчиках, можно еще больше упростить.
class OrderProcessor:
def __init__(self):
self.handlers = {
"new": [validate_order, process_payment, send_confirmation_email],
...
}
def __call__(self, order_data):
status = order_data['status']
if status in self.handlers:
for handler in self.handlers[status]:
reuslt = handler(order_data)
else:
logger.warning(f"Unknown order status: {status}")
result = {"error": "Unknown status"}
return result
а теперь можно просто выкладывать сгенерированный текст ИИ просто в качестве статьи и называть это Best Practices?
Это же просто копипаст ответа курсора)
Этот период надо просто пережить, а аккаунты тех, кто постит эту субстанцию, банить нещадно.
Со временем народ поймет, что это бесполезно.
это факт, просто становится грустно наблюдать что AI который должен вроде как давать знания, так как это доступ к такому объему знаний, а по факту я смотрю как только становится больше глупых и перестающих думать.
Но наверное да, просто нужно время
Спасибо за комментарии! Тапок у меня теперь … немерено. Я предложил один из вариантов обхода if-elif-else, и попытался описать этот подход как можно понятнее. Согласен что есть и другие подходы, которые вы написали, за это вам отдельное спасибо!!! Пусть каждый выбирает себе по душе.
очередной AI-slop. зачем вы с этой ерундой на хабр лезете? кого вы здесь хотите обмануть?
даже не удосужился сообщить, что это обычный паттерн «стратегия». видимо уровень автора - выдавать ответы чата за свои.
Как будто ответ ИИ прочитал: эмодзи в тезисах и "python" над блоками кода 🤣
Нужно запилить теперь статью как изящно переписать что то нечитаемое со словарём на if else и обязательно вставить ссылку на тг канал
Визуальная чистота? Легкое расширение?
Принцип единственной ответственности?
Вот в этом god object, в котором каждый метод ещё и в конструкторе зарегистрирован должен быть?
Это шутка такая, я надеюсь?

Python шпильки: как заменить многоэтажные if-else на изящный словарь функций