Эффективный и чистый способ выращивания функции токенизатора в Python - PullRequest
1 голос
/ 06 октября 2011

У меня есть библиотека, которая выполняет "перевод" и использует для этого потрясающую функцию tokenize.generate_tokens().

И это довольно быстро, и у меня все работает правильно. Но при переводе я обнаружил, что функция продолжает расти с новыми токенами, которые я хочу перевести, и условия if и elif начинают появляться повсюду. Я также держу несколько переменных вне генератора, которые отслеживают «последнее увиденное ключевое слово» и тому подобное.

Хорошим примером этого является документация по Python, показанная здесь (внизу): http://docs.python.org/library/tokenize.html#tokenize.untokenize

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

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

Итак, 2 вопроса:

  1. Как можно избежать добавления все большего количества условных выражений, которые сделают эту функцию перевода простой / понятной для продолжения роста (без снижения производительности)?

  2. Как я могу сделать это эффективным для всех не относящихся к делу строк, которые меня не интересуют?

1 Ответ

3 голосов
/ 07 октября 2011

Вы можете использовать диспетчер dict. Например, код, на который вы ссылаетесь, может выглядеть так:

def process_number(result,tokval):
    if '.' in tokval:
        result.extend([
            (NAME, 'Decimal'),
            (OP, '('),
            (STRING, repr(tokval)),
            (OP, ')')
            ])
def process_default(result,tokval):
    result.append((toknum, tokval))

dispatcher={NUMBER: process_number, }
for toknum, tokval, _, _, _  in g:
    dispatcher.get(toknum,process_default)(result,tokval)

Вместо того, чтобы добавлять больше if -блоков, вы добавляете пары ключ-значение к dispatcher.

Это может быть более эффективным, чем вычисление длинного списка if-else условных выражений, поскольку поиск dict равен O(1), но для этого требуется вызов функции. Вам нужно будет сравнить, чтобы сравнить это со многими if-else блоками.

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

...