Оператор Switch-case в Python

Одна из самых шокирующих вещей, которую вы можете обнаружить за первые месяцы использования Python, заключается в том, что оператор switch-case не существует. Возможно, раньше вы работали только с такими языками, как C или Java. Оба они предоставляют вам оператор switch, чтобы избежать ада if-else if.

Конечно, этому есть объяснение; вы можете прочитать полное обсуждение здесь и понять, почему сам Гвидо Ван Россум отверг это.

Функциональность switch-case

В этом посте мы рассмотрим два быстрых обходных пути для реализации функциональности, подобной switch-case.

Давайте поработаем с простым примером. Вам нужно создать сценарий для имитации калькулятора, подумать об основных операциях, которые может выполнять калькулятор: сложение, вычитание, деление и умножение.

def add(a, b):
    return a + b

def subtract(a, b):
    return a - b

def divide(a, b):
    if b == 0: # To catch division by zero errors
        return 'Error dividing by zero' 
    return a // b # To return int instead of float

def multiply(a, b):
    return a * b

Функции управления готовы; давайте добавим "главное" меню, чтобы собрать все воедино.

def calculator(operation_option, a, b):
    int_a, int_b = int(a), int(b) # To cast string values to ints

    if operation_option == 'add':
        result = add(int_a, int_b)

    elif operation_option == 'subtract':
        result = subtract(int_a, int_b)

    elif operation_option == 'divide':
        result = divide(int_a, int_b)

    elif operation_option == 'multiply':
        result = multiply(int_a, int_b)

    else: # Default case
        result = f'Invalid operation {operation_option}'

    return result


if __name__ == ' __main__':
    operation = input('Type operation name: ').lower()
    # lower() will help to manage everything as lowercase

    num_a = input('Type first number: ')
    num_b = input('Type second number: ')

    # since num_a and num_b are mean to be integers
    # lower is unnecessary

    result = calculator(operation, num_a, num_b)

    print(result)

Как вы можете видеть, если пользователь хочет добавить, выполняется только одно сравнение; с другой стороны, если пользователь хочет умножить, выполняются четыре сравнения.

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

Словари

В Python есть встроенный объект, подобный карте, вы знаете, столько пар ключ-значение, сколько вы хотите, они могут хранить неизменяемые объекты в качестве ключей и любой объект в качестве значений.

Этот обходной путь подразумевает использование словаря со строковыми объектами в качестве ключей и функциями в качестве значений.

Давайте перепишем ту же функцию "калькулятор", используя словарь функций

def calculator(operation_option, a, b):

    DEFAULT_VALUE = -1
    int_a, int_b = int(a), int(b) # To cast string values to ints

    operations = {
        'add': add(int_a, int_b),
        'subtract': subtract(int_a, int_b),
        'divide': divide(int_a, int_b),
        'multiply': multiply(int_a, int_b)
    }
    result = operations.get(operation_option, DEFAULT_VALUE)

    return result

Как вы можете видеть, этот обходной путь "преобразует" строку в функцию и выполняет, но эта реализация неверна.

Этот словарь использует строковые объекты в качестве ключей и целые числа в качестве значений; такая реализация может привести к ожиданию, пока все функции не завершат свое выполнение и не заполнят словарь.

Тогда правильный способ - создать словарь со строковыми ключами и значениями функций, давайте создадим этот dict.

def calculator(operation_option, a, b):

    int_a, int_b = int(a), int(b) # To cast string values to ints

    operations = {
        'add': add,
        'subtract': subtract,
        'divide': divide,
        'multiply': multiply
    }
    operation_function = operations.get(operation_option, None)
    # operation_function now points to a function object

    if operation_function is None:
        # If the operation does not exist
        return f'Invalid operation {operation_option}'

    # Invoke the function with parameters
    result = operation_function(int_a, int_b)

    return result

Готово! Это сделает отправку вашей функции проще и быстрее, с этой последней реализацией вы не будете ждать, пока закончатся все условия if или пока не будут выполнены все функции, чтобы заполнить ваш параметр словаря.

Вывод

В данной статье мы узнали что Switch-Сase в Python, в отличии от многих других языках не существует. При этом, есть мы рассмотрели как, все же, реализовать этот функционал на Python. Спасибо за прочтение.