switch-case и if-elif-else в python

Опубликовано: 2011-11-14
Теги: python

Многие кидают камень в огород python за то, что там нет полноценного блока switch-case. Некоторые из огорода python кидают ответный камень говоря про замену в виду if-elif-else

Я не одобряю не тех не других и матерю оба лагеря, ибо считаю что блоки подобные switch-case просто не нужны в большинстве случаев. И в свою очередь if-elif-else как эмуляция именно switch-case тоже бесполезна.

Типичный блок кода с if-elif-else и эмуляцией switch-case:

if token == 1:
    do_something1()
elif token == 2:
    do_something2()
elif token == 3:
    do_something3()
elif token == 4:
    do_something4()
elif token == 5:
    do_something5()
else:
    raise ValueError('unknown token %s' % token)

Это убого и некрасиво.

Теперь красиво:

tokens = (do_something1, do_something2, do_something3,
          do_something4, do_something5)
if token < 1 or token > len(tokens):
    raise ValueError('unkown token %s' % token)

tokens[int(token)-1]()

Аналогично с dict, в случае если token может быть произвольной строкой. Пример сложнее, если в do_something[0-9] передаются произвольные аргументы.

from functools import partial as p
tokens = (p(do_something1, 123), p(do_something2, mykwarg=666),
          p(do_something3, 'arg', mykwarg=777, mykwarg2=888),
          do_something4, p(do_something5, args),)

Далее в точности как в примере выше. Можно обойтись и без functools, и сделать все руками, никаких проблем.

Однако, if-elif-else может быть полезен, но только в том случае, когда он не используется как замена для swtich-case. Пример из cyrax:

def parse_line(line):
    key, value = strip(line.split(':', 1))
    s, e = value.startswith, value.endswith
    if s('[') and e(']'):
        value = strip(value[1:-1].split(','))
    elif s('{') and e('}'):
        value = dict(strip(x.split(':')) for x in value[1:-1].split(','))
    elif s('date:'):
        value = parse_date(value[len('date:'):].strip())
    elif key.strip() == 'date':
        try:
            value = parse_date(value)
        except ValueError:
            pass
    elif value.lower() in 'true yes on'.split():
        value = True
    elif value.lower() in 'false no off'.split():
        value = False
    return key, value
blog comments powered by Disqus

Блог

Работает на движке cyrax. В качестве шаблона модифицированная тема "Clean Minimal" от themelab.com.