«Pythonic» эквивалент для обработки переключателя и сравнения нескольких строк - PullRequest
8 голосов
/ 13 марта 2009

Хорошо, так что мой заголовок отстой. Пример работает лучше:

input = 'check yahoo.com'

Я хочу проанализировать ввод, используя первое слово в качестве «команды», а остальную часть строки в качестве параметра. Вот простая версия того, как мой непифонический разум его кодирует:

if len(input) > 0:
    a = input.split(' ')
    if a[0] == 'check':
        if len(a) > 1:
            do_check(a[1])
    elif a[0] == 'search':
        if len(a) > 1:
            do_search(a[1])

Мне нравится Python, потому что он обычно превращает сложные вещи в довольно простые. Я не слишком опытен в этом, и я уверен, что есть гораздо лучший способ сделать это ... немного более питонический. Я видел несколько примеров, когда люди заменяли операторы switch на dict и lambda-функции, тогда как другие просто рекомендовали if..else nests.

Ответы [ 6 ]

31 голосов
/ 13 марта 2009
dispatch = {
  'check': do_check,
  'search': do_search,
}
cmd, _, arg = input.partition(' ')
if cmd in dispatch:
    dispatch[cmd](arg)
else:
    do_default(cmd, arg)
4 голосов
/ 13 марта 2009

Я вполне уверен, что есть гораздо лучший способ сделать это ... немного более питонически.

Не совсем. Ваш код прост, понятен, очевиден и похож на английский.

Я видел несколько примеров того, как люди заменяли операторы switch на функции dict и lambda,

Да, вы видели их, и они не ясны, не очевидны или похожи на английский. Они существуют, потому что некоторые люди любят складывать руки над оператором switch.

в то время как другие люди просто рекомендуют, если .. еще гнезда.

Правильно. Они работают. Они простые, понятные, ...

Ваш код хорош. Оставить это в покое. Двигайся.

3 голосов
/ 13 марта 2009

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

class CommandFunctions:
    def c_check(self, arg):
        print "checking", arg

    def c_search(self, arg):
        print "searching for", arg

    def c_compare(self, arg1, arg2):
        print "comparing", arg1, "with", arg2

    def execute(self, line):
        words = line.split(' ')
        fn = getattr(self, 'c_' + words[0], None)
        if fn is None:
            import sys
            sys.stderr.write('error: no such command "%s"\n' % words[0])
            return
        fn(*words[1:])

cf = CommandFunctions()
import sys
for line in sys.stdin:
    cf.execute(line.strip())
0 голосов
/ 13 июня 2009

Вариация @ ответ MizardX :

from collections import defaultdict

dispatch = defaultdict(do_default, check=do_check, search=do_search)
cmd, _, arg = input.partition(' ')
dispatch[cmd](arg)
0 голосов
/ 16 марта 2009

Не обращайте внимания, я просто понял, что мой ответ был похож на один из других ответов - и, видимо, нет ключа удаления:)

0 голосов
/ 13 марта 2009

Если вы ищете «питонический» подход с одним вкладышем, вы можете использовать это:


def do_check(x): print 'checking for:', x
def do_search(x): print 'searching for:', x

input = 'check yahoo.com'
{'check': do_check}.get(input.split()[0], do_search)(input.split()[1])
# checking for: yahoo.com

input = 'search google.com'
{'check': do_check}.get(input.split()[0], do_search)(input.split()[1])
# searching for: google.com

input = 'foo bar.com'
{'check': do_check}.get(input.split()[0], do_search)(input.split()[1])
# searching for: bar.com
...