Продолжить цикл без итерации - PullRequest
0 голосов
/ 19 сентября 2018

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

for line in file_as_list:
    response = input(line)
    if response.lower() == 'help':
        self.show_command_list()
        response = input(line)
    if response.lower() == 'loc':
        self.show_location(file_as_list, location)
        response = input(line)
    if response.lower() == 'exit':
        save_changes = input('Would you like to save the changes you have made? (Y/N) ')
        while (save_changes.upper() != 'Y') & (save_changes.upper() != 'N'):
            save_changes = input('That is not a valid response. Try again. ')
        if save_changes.upper() == 'N':
            temp = file_as_list
            print('Changes were not saved.')
        else:
            for line in file_as_list[location:]:
                temp.append(line)
            print('Changes were saved.')
        break
    if response.lower() == 'inline':
        line += ' //' + input(line + ' //')
        print('Line generated: ' + line)
    location += 1
    temp.append(line)

Ответы [ 3 ]

0 голосов
/ 19 сентября 2018

Я думаю, вы хотите две вложенные петли.Попробуйте что-то вроде этого:

for line in file_as_list:   # outer loop
    while True:             # inner loop
        response = input(line).lower()
        if response == 'help':        # these two options don't exit the inner loop
            ...
        elif response == 'loc':       # so they won't consume a line from the for loop
            ...
        else:
            break

    if response == 'exit':            # these other two conditions are outside the while loop
        ...
    elif response == 'inline':        # so a new line will be fetched after they run
        ...

Если будет выполнено любое из первых двух условий, внутренний цикл продолжит работать без изменения line.Только в случае попадания break внутренний цикл завершается, а остальные условия проверяются.После того, как они сделают свое дело, новое значение будет присвоено line, поскольку цикл for продолжает повторяться.

Вне зависимости от вашего основного вопроса, я также изменил строку input на вызов lower на входе непосредственно перед сохранением его на response.Это означает, что условия не должны вызывать его повторно.Ваш код не ошибается, но если вы никогда не заботитесь о капитализации пользователя, выброс его сразу же может упростить ситуацию.

0 голосов
/ 19 сентября 2018

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

Преимущество этого состоит в том, что в настоящее время ваши описательные команды, такие как "help" и "loc", не могут повторяться, но вы, вероятно, хотитеони должны быть.

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

Следующая концепция имеет набор функций, которые возвращают логическое значение из трех состояний и обновление.Логическое значение True, если команда хочет остаться на текущей строке, False для продолжения.Нет, чтобы выйти.Обновление строки обычно является только вводом.

# in __init__
...
   self.command_map = {
        'help': self.help,
        'loc': , self.loc,
        'exit': self.exit,
        'inline': self.inline,
    }
    self.temp = []
...

def help(self, file_as_list, location, line):
    self.show_command_list()
    return True, line

def loc(self, file_as_list, location, line):
    self.show_location(file_as_list, location)
    return True, line

def exit(self, file_as_list, location, line):
    save_changes = ''
    while len(save_changes) != 1 or save_changes.upper() not in 'YN':
        save_changes = input('Would you like to save the changes you have made? (Y/N) ')
    if save_changes.upper() == 'N':
        self.temp = file_as_list
        print('Changes were not saved.')
    else:
        self.temp.extend(file_as_list[location:])
        print('Changes were saved.')
    return None, line

def inline(self, file_as_list, location, line):
    line += ' //' + input(line + ' //')
    print('Line generated: ' + line)
    return True, line

def process(self):
    for location, line in enumerate(file_as_list):
        stay = True
        while stay:
            response = input(line)
            command = command_map.get(response.casefold())
            if command is None:
                print(f'Command "{response}" not found. Try again')
            else:
                stay, line = command(file_as_list, location, line)

        if stay is None:
            break
        self.temp.append(line)

Учитывая command_map, вы можете сделать много вещей проще: например, вы можете переопределить show_command_list, чтобы что-то сделать с sorted(command_map.keys()).Я уверен, что вы можете видеть, как легко добавить команды в свой список.Вам не нужно повторять шаблонный код, просто будьте осторожны с входными данными и возвращаемыми значениями.

Эту конструкцию также намного проще выполнить вручную, если вам не нравится идея иметь вложенные циклы:

def process(self):
    stay = False
    iterator = enumerate(file_as_list)
    while True:
        if not stay:
            try:
                location, line = next(iterator)
            except StopIteration:
                break
        response = input(line)
        command = command_map.get(response.casefold())
        if command is None:
            print(f'Command "{response}" not found. Try again')
            stay = True
        else:
            stay, line = command(file_as_list, location, line)

        if stay is None:
            break
        if not stay:
            self.temp.append(line)

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

0 голосов
/ 19 сентября 2018

Вы можете использовать явный итератор, такой как

it = iter(file_as_list)
for line in it:
    input(line)
   ... 
    input(next(it))

и так далее.Просто убедитесь, что правильно справились со случаем, когда у вас закончились линии!

...