Есть ли какое-либо значение для реализации Switch / Case в Python? - PullRequest
3 голосов
/ 26 марта 2011

Недавно я видел в Интернете некоторые дискуссии о том, что в Python нет хорошего эквивалента «переключатель / регистр».Я понимаю, что есть несколько способов сделать что-то подобное - некоторые с помощью лямбды, некоторые со словарями.Были и другие обсуждения StackOverflow об альтернативах.Были даже два PEP (PEP 0275 и PEP 3103), обсуждающие (и отвергающие) интеграцию switch / case в язык.

Я придумал элегантный способ сделать switch / case.

В конечном итоге это выглядит так:

from switch_case import switch, case         # note the import style

x = 42
switch(x)                                    # note the switch statement
if case(1):                                  # note the case statement
    print(1)
if case(2):
    print(2)
if case():                                   # note the case with no args
    print("Some number besides 1 or 2")

Итак, мои вопросы: это стоящее создание?Есть ли у вас какие-либо предложения по его улучшению?

Я поместил включаемый файл на github вместе с обширными примерами.(Я думаю, что весь включаемый файл составляет около 50 исполняемых строк, но у меня есть 1500 строк примеров и документации.) Я перерабатывал эту вещь и тратил кучу времени, или кто-то найдет это стоящим?

Редактировать:

Попытка объяснить, почему это отличается от других подходов:
1) Возможно несколько путей (выполнение двух или более случаев), что сложнее в методе словаря.
2) может выполнять проверку для сравнения, отличного от «равно» (например, case (less_than (1000)).
3) Более читабельно, чем метод словаря, и, возможно, если метод / elif
4) может отслеживать, сколько Trueслучаи были.
5) может ограничивать количество истинных случаев.(т.е. выполнить первые 2 истинных случая ...)
6) допускает случай по умолчанию.

Вот более сложный пример:

from switch_case import switch, case, between

x=12
switch(x, limit=1)                # only execute the FIRST True case
if case(between(10,100)):         # note the "between" case Function
    print ("%d has two digits."%x)
if case(*range(0,100,2)):         # note that this is an if, not an elif!
    print ("%d is even."%x)       # doesn't get executed for 2 digit numbers,
                                  # because limit is 1; previous case was True.
if case():
    print ("Nothing interesting to say about %d"%x)



# Running this program produces this output:

12 has two digits.

Вот пример, пытающийся показать, как switch_case может быть более понятным и лаконичным, чем обычный if / else:

# conventional if/elif/else:
if (status_code == 2 or status_code == 4 or (11 <= status_code < 20) 
          or status_code==32):
    [block of code]
elif status_code == 25 or status_code == 45:
    [block of code]
if status_code <= 100:
    [block can get executed in addition to above blocks]

# switch_case alternative (assumes import already)
switch(status_code)
if case (2, 4, between(11,20), 32):   # significantly shorter!
    [block of code]
elif case(25, 45):
    [block of code]
if case(le(100)):
    [block can get executed in addition to above blocks]

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

Файл примера на github содержит еще больше примеров.

Ответы [ 5 ]

6 голосов
/ 26 марта 2011

Итак, мои вопросы: это стоящее творение?

номер

У вас есть предложения по улучшению?

Да. Не беспокойся Что это спасло? Шутки в сторону? Вы фактически сделали код более неясным, удалив переменную x из каждого условия elif. Также, заменив очевидное elif на if, вы создали намеренную путаницу для всего Python программисты, которые теперь будут думать, что случаи независимы.

Это создает путаницу.

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

Нет. Это очень редко, очень надумано и очень трудно читать. Просмотр фактической переменной (ов) имеет важное значение. Исключение имени переменной делает вещи намеренно запутанными. Теперь мне нужно найти собственную switch() функцию для интерпретации case.

Когда есть две или более переменных, это полностью разрушается.

4 голосов
/ 26 марта 2011

ИМХО, главная причина существования оператора switch заключается в том, что его можно преобразовать / скомпилировать в (очень быструю) таблицу переходов . Как бы ваша предложенная реализация достигла этой цели? Словари Python делают это сегодня, как показали другие авторы.

Во-вторых, я думаю, что оператор switch может читаться более четко, чем альтернативы в некоторых языках, но в случае с python я думаю, if / elif / else выигрывает в ясности.

4 голосов
/ 26 марта 2011

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

Однако я не вижу, насколько ваше решение лучше базового словаря:

def switch(x):
    return {
        1 : 1,
        2 : 2,
    }[x]

Хотя, добавление предложения по умолчанию не является тривиальным с этим методом. Тем не менее, ваш пример, похоже, все равно воспроизводит сложный оператор if / else? Не уверен, что я бы включил внешнюю библиотеку для этого.

3 голосов
/ 27 марта 2011
from pyswitch import Switch   # pyswitch can be found on PyPI

myswitch = Switch()

@myswitch.case(42)
def case42(value):
    print "I got 42!"

@myswitch.case(range(10))
def caseRange10(value):
    print "I got a number from 0-9, and it was %d!" % value

@myswitch.caseIn('lo')
def caseLo(value):
    print "I got a string with 'lo' in it; it was '%s'" % value

@myswitch.caseRegEx(r'\b([Pp]y\w)\b')
def caseReExPy(matchOb):
    print r"I got a string that matched the regex '\b[Pp]y\w\b', and the match was '%s'" % matchOb.group(1)

@myswitch.default
def caseDefault(value):
    print "Hey, default handler here, with a value of %r." % value

myswitch(5)  # prints: I got a number from 0-9, and it was 5!
myswitch('foobar')  # prints: Hey, default handler here, with a value of foobar.
myswitch('The word is Python')  # prints: I got a string that matched the regex '\b[Pp]y\w\b', and the match was 'Python'

Вы поняли идею.Зачем?Да, таблицы отправки - это путь в Python.Я просто устал писать их снова и снова, поэтому я написал класс и несколько декораторов, чтобы справиться с этим для меня.

3 голосов
/ 26 марта 2011

Я всегда использовал словари, если / elses, или лямбда-выражения для своих выражений типа switch. Читая ваш код, хотя =)

документы:

why-isn-t-there-a-switch-or-case-statement-in-python

...