Mam trochę list składanych w Pythonie, w których każda iteracja może zgłosić wyjątek.
Na przykład , jeśli mam:
eggs = (1,3,0,3,2)
[1/egg for egg in eggs]
W ZeroDivisionError
trzecim elemencie dostanę wyjątek.
Jak mogę obsłużyć ten wyjątek i kontynuować przetwarzanie listy?
Jedyny sposób, jaki przychodzi mi do głowy, to użycie funkcji pomocniczej:
def spam(egg):
try:
return 1/egg
except ZeroDivisionError:
# handle division by zero error
# leave empty for now
pass
Ale wydaje mi się to trochę kłopotliwe.
Czy jest lepszy sposób na zrobienie tego w Pythonie?
Uwaga: to jest prosty przykład (patrz „ na przykład ” powyżej), który wymyśliłem, ponieważ mój prawdziwy przykład wymaga kontekstu. Nie interesuje mnie unikanie błędów dzielenia przez zero, ale obsługa wyjątków przy przetwarzaniu list.
python
exception
list-comprehension
Nathan Fellman
źródło
źródło
[1/egg except ZeroDivisionError: None for egg in (1,3,0,3,2)]
. Ale nadal jest w trybie roboczym. Mam przeczucie, że nie zostanie to zaakceptowane. Wyrażenia Imho mogą być zbyt nieporządne (sprawdzanie wielu wyjątków, bardziej złożone kombinacje (wiele operatorów logicznych, złożonendarray
z odpowiednimi ustawieniami wnp.seterr
. To by skutkowało1/0 = nan
. Ale zdaję sobie sprawę, że nie dotyczy to innych sytuacji, w których pojawia się taka potrzeba.Odpowiedzi:
W Pythonie nie ma wbudowanego wyrażenia, które pozwala zignorować wyjątek (lub zwrócić alternatywne wartości & cw przypadku wyjątków), więc dosłownie niemożliwe jest „obsłużenie wyjątków przy przetwarzaniu listowym”, ponieważ wyrażenie listy jest wyrażeniem zawierające inne wyrażenie, nic więcej (tj. brak instrukcji i tylko instrukcje mogą przechwytywać / ignorować / obsługiwać wyjątki).
Wywołania funkcji są wyrażeniami, a treści funkcji mogą zawierać wszystkie żądane instrukcje, więc delegowanie oceny wyrażenia podrzędnego podatnego na wyjątki do funkcji, jak zauważyłeś, jest jednym możliwym obejściem (inne, jeśli to możliwe, to sprawdzanie wartości, które mogą wywoływać wyjątki, co sugeruje również inne odpowiedzi).
Prawidłowe odpowiedzi na pytanie „jak postępować z wyjątkami w zrozumieniu listowym” wyrażają część całej tej prawdy: 1) dosłownie, tj. Leksykalnie, W samym zrozumieniu nie możesz; 2) praktycznie delegujesz zadanie do funkcji lub sprawdzasz wartości podatne na błędy, jeśli jest to wykonalne. Twoje powtarzające się twierdzenie, że to nie jest odpowiedź, jest zatem bezpodstawne.
źródło
[x[1] for x in list except IndexError pass]
. Czy tłumacz nie mógł utworzyć tymczasowej funkcji do wypróbowaniax[1]
?Zdaję sobie sprawę, że to pytanie jest dość stare, ale możesz także utworzyć ogólną funkcję, aby ułatwić tego rodzaju czynności:
Następnie, w twoim zrozumieniu:
Możesz oczywiście ustawić domyślną funkcję uchwytu, jaką chcesz (powiedzmy, że wolisz domyślnie zwrócić „Brak”).
Mam nadzieję, że pomoże to Tobie lub przyszłym widzom tego pytania!
Uwaga: w Pythonie 3 utworzyłbym tylko słowo kluczowe argumentu „handle” i umieściłbym je na końcu listy argumentów. To sprawiłoby, że faktyczne przekazywanie argumentów i tego typu przechwytywanie byłoby znacznie bardziej naturalne.
źródło
args
i przejście równieżkwargs
do obsługi. W ten sposób możesz powrócić, powiedzegg
zamiast zakodowanego na stałe0
, lub wyjątek, tak jak robisz.handle
po**kwarg
i otrzymałemSyntaxError
. Czy masz na myśli wyłuskać jakokwargs.get('handle',e)
?Możesz użyć
spowoduje to po prostu pominięcie elementów, które są zerowe.
źródło
Nie, nie ma lepszego sposobu. W wielu przypadkach możesz użyć unikania, tak jak robi to Peter
Inną opcją jest nie używanie rozumienia
Do Ciebie należy decyzja, czy jest to bardziej uciążliwe, czy nie
źródło
Myślę, że funkcja pomocnicza, jak sugeruje osoba zadająca pierwsze pytanie, a także Bryan Head, jest dobra i wcale nie uciążliwa. Pojedynczy wiersz magicznego kodu, który wykonuje całą pracę, po prostu nie zawsze jest możliwy, więc funkcja pomocnicza jest idealnym rozwiązaniem, jeśli chcesz uniknąć
for
pętli. Jednak zmodyfikowałbym to do tego:Wynik będzie taki
[(1/1, None), (1/3, None), (None, ZeroDivisionError), (1/3, None), (1/2, None)]
. Dzięki tej odpowiedzi masz pełną kontrolę nad kontynuowaniem w dowolny sposób.źródło
Either
typu w niektórych funkcjonalnych językach programowania (takich jak Scala), gdzie anEither
może zawierać wartość jednego lub drugiego typu, ale nie obu. Jedyna różnica polega na tym, że w tych językach idiomatyczne jest umieszczenie błędu po lewej stronie, a wartości po prawej stronie. Oto artykuł z dodatkowymi informacjami .Nie widziałem żadnej odpowiedzi, która o tym wspominała. Ale ten przykład byłby jednym ze sposobów zapobiegania zgłaszaniu wyjątku dla znanych przypadków niepowodzenia.
źródło