Избегайте, если-иначе, Pythonic Ways
Операторы if-else являются фундаментальной управляющей структурой в программировании. Однако код, который в значительной степени зависит от операторов if-else, менее удобочитаем и менее удобен в сопровождении. К счастью, с Python мы можем легко избежать операторов if-else. В этом сообщении блога мы рассмотрим шесть способов Pythonic, позволяющих избежать операторов if-else.
Следует ли полностью избегать if-elif-else?
Краткий ответ: Нет. Когда условная логика проста, мы можем использовать if-else
.
def number_classification(number): if number > 0: return "Positive" elif number < 0: return "Negative" else: return "Zero"
В этом примере мы хотим классифицировать, является ли число положительным, отрицательным или нулем. Логика проста, поэтому можно использовать if-elif-else
. Кстати, от блока else
здесь можно избавиться.
1. Ненужное еще
def is_even(number): if number % 2 == 0: return True else: return False
Приведенный выше код проверяет, является ли число четным. В его логике нет ничего плохого. Однако блок else
не нужен, и от него можно легко избавиться.
def is_even(number): if number % 2 == 0: return True return False
Во многих случаях блок else
вообще не нужен. Если определенное условие выполнено, просто верните что-то немедленно.
Другой случай, когда от else
можно легко избавиться, — это когда if-else
используется для присвоения значения переменным. Присвоение значения по умолчанию может значительно упростить ваш код.
# No, we can do better than this if condition: number = 1 else: number = 2 # Just use a default vlue number = 2 if condition: number = 1
2. Присвоение ценности
Новые программисты довольно часто используют if-else
для присвоения нового значения переменной в зависимости от заданного ввода.
def classify_temperature(temperature): message = '' if temperature >= 26: message = "Hot" elif temperature >= 15: message = "Warm" else: message = "Cold" return message
В этом примере у нас есть функция, которая принимает температуру в градусах Цельсия и классифицирует температуру как горячую, теплую или холодную. Эта функция очень проста и удобочитаема, но ее еще можно улучшить. Блоки elif
и else
не нужны.
def classify_temperature(temperature): if temperature >= 26: return "Hot" if temperature >= 15: return "Warm" return "Cold"
3. Защитные оговорки
Охранные оговорки также известны как досрочное возвращение. Охранные предложения — это способ упростить поток управления в функции или методе, возвращая или вызывая исключение, как только выполняется условие раннего выхода. Это может помочь устранить необходимость в операторах else
и сделать код более читабельным, удобным для сопровождения, а также тестируемым. На мой взгляд, нет смысла продолжать работу функции, если она снабжена неверными входными данными.
Код раннего возврата выглядит так:
def my_function(): if not condition: return # or raise an Exception # Do something def my_function_reverse_condition(): if condition: # Do something return # or raise an Exception
В приведенном ниже примере версия с защитными предложениями более удобочитаема, так как каждое условие проверяется и обрабатывается отдельно. Эта версия также не требует нескольких else
.
# Using guard clauses def validate_input(input_list): if not isinstance(input_list, list): raise TypeError("Input must be a list.") if not input_list: raise ValueError("Input cannot be an empty list.") if not all(isinstance(item, float) for item in input_list): raise ValueError("All items in the list must be floats.") return True # Using if-else statements def validate_input(input_list): if isinstance(input_list, list): if input_list: if all(isinstance(item, float) for item in input_list): return True else: raise ValueError("All items in the list must be floats.") else: raise ValueError("Input cannot be an empty list.") else: raise TypeError("Input must be a list.")
4. Словарь
Словарь Python — настоящее обезболивающее, когда нам нужно работать с большим количеством операторов if-else
. С помощью словаря Python мы можем сопоставить каждое входное значение с соответствующим действием или значением.
# lots of if-elif def determine_favorite_fruit(color): if color == "red": return "Strawberry" elif color == "yellow": return "Banana" elif color == "green": return "Honeydew" return "unknown" # Dictionary is used def determine_favorite_fruit_with_dict(color): color_to_fruit = { "red": "Strawberry", "yellow": "Banana", "green": "Honeydew", } return color_to_fruit.get(color, "unknown")
Использование словарей Python значительно улучшает читаемость нашего кода. Кроме того, он также более гибкий. Бывают случаи, когда нам нужно добавить больше случаев в наш код. При подходе if-elif-else
нам нужно добавить в метод еще один блок кода. При подходе со словарем нам просто нужно изменить наш словарь, не затрагивая остальную часть кода. Еще одним преимуществом является повышенная эффективность, поскольку в Python поиск по словарю обычно выполняется быстрее, чем повторение ряда if-else
условий.
5. Матч
Начиная с Python 3.10, мы можем использовать match
для сопоставления с образцом. Благодаря этой функции мы можем попрощаться с длинными цепочками if-elif
.
match value: case pattern_1: # code to execute if value matches pattern_1 case pattern_2: # code to execute if value matches pattern_2 ... case pattern_n: # code to execute if value matches pattern_n case _: # code to execute if value matches pattern_n
_
(подчеркивание) — это шаблон подстановки, который соответствует любому значению.
def use_if_else(value): if value == 1: print("Value is 1") elif value == 2: print("Value is 2") elif value == 3: print("Value is 3") else: print("Value is something else") def use_match(value): match value: case 1: print("Value is 1") case 2: print("Value is 2") case 3: print("Value is 3") case _: print("Value is something else")
По сравнению с методом if-elif
, match
делает код более читабельным.
6. Паттерн стратегии
Шаблон стратегии — это шаблон проектирования в разработке программного обеспечения, который позволяет выбирать поведение класса во время выполнения.
Пример: Наш веб-сайт позволяет клиентам использовать различные способы оплаты, такие как кредитные карты и Paypal. Ниже приведен пример не использования шаблона стратегии. Используется довольно много if-elif-else
:
def pay_with_credit_card(amount): print(f"Paying {amount} using credit card.") def pay_with_paypal(amount): print(f"Paying {amount} using PayPal.") def pay(amount, method): if method == "credit_card": pay_with_credit_card(amount) elif method == "paypal": pay_with_paypal(amount) else: raise ValueError("Unsupported payment method")
Если stripe
также разрешен в качестве способа оплаты, мы должны изменить метод pay
. Тем более if-elif-else
. Еще одна причина, по которой эта практика плоха: она нарушает принцип открытого-закрытого (SOLID Principles).
def pay_with_credit_card(amount): print(f"Paying {amount} using credit card.") def pay_with_paypal(amount): print(f"Paying {amount} using PayPal.") def pay_with_stripe(amount): print(f"Paying {amount} using Stripe.") def pay(amount, method): if method == "credit_card": pay_with_credit_card(amount) elif method == "paypal": pay_with_paypal(amount) elif method == "stripe": pay_with_stripe(amount) else: raise ValueError("Unsupported payment method")
Мы можем добиться большей ремонтопригодности, ограничив if-elif-else
шаблоном стратегии. Когда метод pay
вызывается в контексте PaymentContext
, он делегирует платеж текущей платежной стратегии.
from abc import ABC, abstractmethod # Define the abstract Strategy class class PaymentStrategy(ABC): @abstractmethod def pay(self, amount): pass # Define the concrete Strategy classes class CreditCardPayment(PaymentStrategy): def pay(self, amount): print(f"Paying {amount} using credit card.") class PayPalPayment(PaymentStrategy): def pay(self, amount): print(f"Paying {amount} using PayPal.") class StripePayment(PaymentStrategy): def pay(self, amount): print(f"Paying {amount} using Stripe.") # Define the Context class that will use the Strategy pattern class PaymentContext: def __init__(self, payment_strategy: PaymentStrategy): self.payment_strategy = payment_strategy def set_payment_strategy(self, payment_strategy: PaymentStrategy): self.payment_strategy = payment_strategy def pay(self, amount): self.payment_strategy.pay(amount) # Example usage payment_context = PaymentContext(CreditCardPayment()) payment_context.pay(100) # Output: Paying 100 using credit card. payment_context.set_payment_strategy(PayPalPayment()) payment_context.pay(50) # Output: Paying 50 using PayPal. payment_context.set_payment_strategy(StripePayment()) payment_context.pay(150) # Output: Paying 150 using Stripe.
«🔔 Хотите больше таких статей? Подпишите здесь."
Спасибо за прочтение. Надеюсь, эти 6 трюков будут вам полезны.
Повышение уровня кодирования
Спасибо, что являетесь частью нашего сообщества! Перед тем, как ты уйдешь:
- 👏 Хлопайте за историю и подписывайтесь на автора 👉
- 📰 Смотрите больше контента в публикации Level Up Coding
- 💰 Бесплатный курс собеседования по программированию ⇒ Просмотреть курс
- 🔔 Подписывайтесь на нас: Twitter | ЛинкедИн | "Новостная рассылка"
🚀👉 Присоединяйтесь к коллективу талантов Level Up и найдите прекрасную работу