Подтвердить что ты не робот

Как обрабатывать исключения в списке пониманий?

У меня есть некоторое понимание списка в Python, в котором каждая итерация может вызывать исключение.

Например, если у меня есть:

eggs = (1,3,0,3,2)

[1/egg for egg in eggs]

Я получаю исключение ZeroDivisionError в третьем элементе.

Как я могу обработать это исключение и продолжить выполнение понимания списка?

Единственный способ, которым я могу думать, - использовать вспомогательную функцию:

def spam(egg):
    try:
        return 1/egg
    except ZeroDivisionError:
        # handle division by zero error
        # leave empty for now
        pass

Но это выглядит немного громоздким для меня.

Есть ли лучший способ сделать это в Python?

Примечание.. Это простой пример (см. "например" выше), который я нарисовал, потому что мой реальный пример требует некоторого контекста. Я не заинтересован в том, чтобы избежать деления на нулевые ошибки, но в обработке исключений в понимании списка.

4b9b3361

Ответ 1

В Python нет встроенного выражения, которое позволяет игнорировать исключение (или возвращать переменные значения & c в случае исключений), поэтому в буквальном смысле это невозможно "обрабатывать исключения в понимании списка", поскольку List - это выражение, содержащее другое выражение, не более (т.е. не), и только инструкции могут захватывать/игнорировать/обрабатывать исключения).

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

Правильные ответы на вопрос "как обрабатывать исключения в понимании списка" все выражают часть всей этой истины: 1) буквально, то есть лексически в самом понимании, вы не можете; 2) практически, вы делегируете задание функции или проверяете значения подверженности ошибкам, когда это возможно. Ваше повторное утверждение о том, что это не ответ, является таким образом необоснованным.

Ответ 2

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

def catch(func, handle=lambda e : e, *args, **kwargs):
    try:
        return func(*args, **kwargs)
    except Exception as e:
        return handle(e)

Затем, по вашему пониманию:

eggs = (1,3,0,3,2)
[catch(lambda : 1/egg) for egg in eggs]
[1, 0, ('integer division or modulo by zero'), 0, 0]

Вы можете, конечно, сделать функцию дескриптора по умолчанию тем, что хотите (скажем, вы предпочитаете возвращать "Нет" по умолчанию).

Надеюсь, это поможет вам или будущим зрителям в этом вопросе!

Примечание: в python 3 я бы сделал только ключевое слово аргумента "handle" и поместил его в конец списка аргументов. Это сделало бы фактически передачу аргументов и, таким образом, поймать гораздо более естественным.

Ответ 3

Вы можете использовать

[1/egg for egg in eggs if egg != 0]

это просто пропустит нулевые элементы.

Ответ 4

Нет лучшего способа. Во многих случаях вы можете использовать избегание, как Питер.

Другим вариантом является не использование понятий

eggs = (1,3,0,3,2)

result=[]
for egg in eggs:
    try:
        result.append(egg/0)
    except ZeroDivisionError:
        # handle division by zero error
        # leave empty for now
        pass

До вас, чтобы решить, является ли это более громоздким или нет

Ответ 5

Я считаю, что вспомогательная функция, предложенная тем, кто задает начальный вопрос и Брайан Хед, хороша и не громоздка вообще. Единственная строка магического кода, которая выполняет всю работу, не всегда возможна, поэтому вспомогательная функция является идеальным решением, если вы хотите избежать циклов for. Однако я бы изменил его на следующий:

# A modified version of the helper function by the Question starter 
def spam(egg):
    try:
        return 1/egg, None
    except ZeroDivisionError as err:
        # handle division by zero error        
        return None, err

Выход будет таким [(1/1, None), (1/3, None), (None, ZeroDivisionError), (1/3, None), (1/2, None)]. С помощью этого ответа вы полностью контролируете, чтобы продолжить, каким бы вы ни хотели.

Ответ 6

Зачастую вы можете исключать исключения с помощью предложений if, которые МОГУТ быть помещены в понимание списка:

[1/egg if egg!=0 else 'whatever you want' for egg in eggs]

Это не исключение, и вы можете обработать 0 случай так, как вам хотелось бы