Как я могу обрабатывать исключения в понимании списка в Python?
у меня есть некоторое понимание списка в Python, в котором каждая итерация может бросить исключение.
например, если у меня есть:
eggs = (1,3,0,3,2)
[1/egg for egg in eggs]
Я ZeroDivisionError
исключение в 3-м элементе.
как я могу обработать это исключение и продолжить выполнение постижение список?
единственный способ, который я могу придумать, это использовать вспомогательную функцию:
def spam(egg):
try:
return 1/egg
except ZeroDivisionError:
# handle division by zero error
# leave empty for now
pass
но это выглядит немного громоздко для меня.
- Это есть лучший способ сделать это в Python?
Примечание: это простой пример (см. "например" выше), что я придумал, потому что мой реальный пример требует некоторого контекста. Я не заинтересован в том, чтобы избежать деления на ноль ошибок, но в обработке исключений в список понимания.
5 ответов:
в Python нет встроенного выражения, которое позволяет игнорировать исключение (или возвращать альтернативные значения &c в случае исключений), поэтому невозможно, буквально говоря, "обрабатывать исключения в понимании списка", потому что понимание списка-это выражение, содержащее другое выражение, не более того (т. е. нет операторы, и только операторы могут перехватывать/игнорировать/обрабатывать исключения).
вызовы функций являются выражением, и тела функций могут включать все инструкции, которые вы хотите, поэтому делегирование оценки подверженного исключениям подвыражения функции, как вы заметили, является одним из возможных обходных путей (другие, когда это возможно, являются проверками значений, которые могут вызвать исключения, как также предлагается в других ответах).
правильные ответы на вопрос "как обрабатывать исключения в понимании списка" все выражают часть всей этой истины: 1) буквально, т. е. лексически в самом понимании, вы не можете; 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" и поместил его в конец списка аргументов. Это сделало бы фактически проходящие Аргументы и такие через улов гораздо более естественными.
можно использовать
[1/egg for egg in eggs if egg != 0]
это будет просто пропустить элементы, которые равны нулю.
нет лучшего способа. Во многих случаях вы можете использовать избегание, как это делает Питер
другой вариант-не использовать списочные
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
до вас, чтобы решить, является ли это более громоздким или нет
Я думаю, что вспомогательная функция, предложенная тем, кто задает начальный вопрос, а также Брайан Хед, хороша и совсем не громоздка. Одна строка магического кода, которая делает всю работу, просто не всегда возможна, поэтому вспомогательная функция является идеальным решением, если вы хотите избежать
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)]
. С этим ответом вы находитесь в полном контроле, чтобы продолжить в любом случае вы хотите.