Оператор if для проверки внутри оператора try в Python требует выполнения кода в случае возникновения исключения

Я немного озадачен здесь. Вот кусок кода Python:

try:
    if parse[index+1][0] != "5":
        individual_services+=[individual_services_cur]
        individual_services_cur=[]
except IndexError:
    warning("Reached end of file. No next element")
    individual_services+=[individual_services_cur]
    individual_services_cur=[]

В основном я хочу эти два действия (дополнение individual_services_cur список к individual_services список и очистка individual_services_cur список), чтобы иметь место, если следующий элемент в parse не "5" или, если он не существует (в основном это конец файла).

Мне интересно, есть ли более элегантный (возможно, даже, как говорится, "питонический") способ написания этого кода, например, без необходимости писать эти два действия дважды. Я не мог придумать ни одного хорошего решения с finally или же else заявления, и кажется, что я не могу избавиться от try заявление, потому что, как только достигнут конец файла, IndexError исключение неизбежно возникает.

5 ответов

Решение

Еще одна идея:

update_i_s = True

try:
    update_i_s= parse[index+1][0] != "5"
except IndexError:
    warning("Reached end of file. No next element")
finally:
    if update_i_s:
        individual_services.append([individual_services_cur]) if flag
        individual_services_cur=[]

flag=True требуется только в том случае, если в файле есть только одна строка, и ее нужно устанавливать только один раз в начале (поэтому не помещайте ее в какие-либо циклы).


РЕДАКТИРОВАТЬ:

Кстати, если есть возможность finally блок может потерпеть неудачу, вы можете сделать что-то вроде этого:

try:
    try:
        update_i_s= parse[index+1][0] != "5"
    except IndexError:
        warning("Reached end of file. No next element")
    finally:
        if update_i_s:
            individual_services.append([individual_services_cur]) if flag
            individual_services_cur=[]
except Exception:
    warning("failed to update individual_services")
    raise

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

try:
    value_to_check = parse[index+1][0]

except IndexError:
    warning("Reached end of file. No next element")
    value_to_check = None
finally:
    if value_to_check != "5":
        individual_services+=[individual_services_cur]
        individual_services_cur=[]

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

badstuff = False
try:
    if parse[index+1][0] != "5":
        badstuff = True
except IndexError:
    warning("Reached end of file. No next element")
    badstuff = True

if badstuff:
    individual_services+=[individual_services_cur]
    individual_services_cur=[]

Если вас это устраивает, вы можете поставить if badstuff: в finally блок, в зависимости от того, что делает остальная часть вашего кода.

В качестве альтернативы, положить individual_services вещи в функции, и вызывать его в обоих местах.

Как насчет

last = len(parse) - 1

if index == last or parse[index + 1][0] != "5":
    individual_services.append(individual_services_cur)
    individual_services_cur = []

Или мыслить нестандартно

if index + 1 not in (index for index, value in enumerate(parse) if value[0] == '5'):
    individual_services+=[individual_services_cur]
    individual_services_cur=[]

куда (index for index, value in enumerate(parse) if value[0] == '5') является генератором, который выдает номер строки в каждой строке, у которой в качестве первого символа указано "5". Это эквивалентно этому:

def has_5s(p):
    '''Yield line numbers that begin with a 5'''
    for index, line in enumerate(p):
        yield index if line[0] == '5'

if index + 1 not in has_5s(parse):
    individual_services+=[individual_services_cur]
    individual_services_cur=[]

Вы просто проверяете, есть ли следующий номер строки (line + 1) является одним из этих номеров строк, полученных генератором. поскольку enumerate и сам генератор ленив, это должно быть очень быстро.

Другие вопросы по тегам