Eu tenho uma compreensão de lista em Python em que cada iteração pode lançar uma exceção.
Por exemplo , se eu tenho:
eggs = (1,3,0,3,2)
[1/egg for egg in eggs]
Vou obter uma ZeroDivisionError
exceção no terceiro elemento.
Como posso lidar com essa exceção e continuar a execução da compreensão da lista?
A única maneira que consigo pensar é usar uma função auxiliar:
def spam(egg):
try:
return 1/egg
except ZeroDivisionError:
# handle division by zero error
# leave empty for now
pass
Mas isso parece um pouco complicado para mim.
Existe uma maneira melhor de fazer isso em Python?
Nota: Este é um exemplo simples (veja " por exemplo " acima) que inventei porque meu exemplo real requer algum contexto. Não estou interessado em evitar erros de divisão por zero, mas em lidar com exceções em uma compreensão de lista.
python
exception
list-comprehension
Nathan Fellman
fonte
fonte
[1/egg except ZeroDivisionError: None for egg in (1,3,0,3,2)]
. Mas ainda está em modo de rascunho. Meu pressentimento é que isso não será aceito. Expressões Imho podem ficar muito confusas (verificando múltiplas exceções, tendo combinações mais complexas (múltiplos operadores lógicos, compreensões complexas, etc.)ndarray
com as configurações apropriadas emnp.seterr
. Isso resultaria em1/0 = nan
. Mas eu percebo que isso não generaliza para outras situações em que essa necessidade surge.Respostas:
Não há nenhuma expressão embutida no Python que permita ignorar uma exceção (ou retornar valores alternativos etc. no caso de exceções), então é impossível, literalmente falando, "lidar com exceções em uma compreensão de lista" porque uma compreensão de lista é uma expressão contendo outra expressão, nada mais (ou seja, nenhuma instrução e apenas as instruções podem capturar / ignorar / manipular exceções).
Chamadas de função são expressão e os corpos de função podem incluir todas as instruções que você deseja, portanto, delegar a avaliação da subexpressão sujeita a exceções a uma função, como você notou, é uma solução alternativa viável (outras, quando viável, são verificações de valores que podem provocar exceções, como também sugerido em outras respostas).
As respostas corretas à questão "como lidar com exceções em uma compreensão de lista" estão todas expressando parte de toda essa verdade: 1) literalmente, isto é, lexicamente NA compreensão em si, você não pode; 2) na prática, você delega o trabalho a uma função ou verifica se há valores sujeitos a erros quando isso for viável. Sua afirmação repetida de que esta não é uma resposta é, portanto, infundada.
fonte
[x[1] for x in list except IndexError pass]
. O intérprete não poderia criar uma função temporária para tentarx[1]
?Sei que essa pergunta é bastante antiga, mas você também pode criar uma função geral para tornar esse tipo de coisa mais fácil:
Então, em sua compreensão:
É claro que você pode fazer com que o identificador padrão funcione como quiser (digamos que você prefira retornar 'Nenhum' por padrão).
Espero que isso ajude você ou qualquer futuro visualizador desta questão!
Nota: em Python 3, eu faria a palavra-chave do argumento 'lidar' apenas, e colocaria no final da lista de argumentos. Isso tornaria a passagem de argumentos e coisas do gênero muito mais naturais.
fonte
args
ekwargs
para lidar também. Dessa forma, você pode retornar digamos emegg
vez de um código fixo0
ou uma exceção como está fazendo.handle
depois**kwarg
e consegui umSyntaxError
. Você quer desreferenciar comokwargs.get('handle',e)
?Você pode usar
isso simplesmente pulará os elementos que são zero.
fonte
Não, não há maneira melhor. Em muitos casos, você pode usar a evitação como Peter faz
Sua outra opção é não usar compreensões
Cabe a você decidir se isso é mais complicado ou não
fonte
Acho que uma função auxiliar, conforme sugerido por aquele que faz a pergunta inicial e por Bryan Head também, é boa e nem um pouco complicada. Uma única linha de código mágico que faz todo o trabalho nem sempre é possível, então uma função auxiliar é uma solução perfeita se alguém quiser evitar
for
loops. No entanto, eu iria modificá-lo para este:A saída será esta
[(1/1, None), (1/3, None), (None, ZeroDivisionError), (1/3, None), (1/2, None)]
. Com essa resposta, você tem controle total para continuar da maneira que quiser.fonte
Either
tipo em algumas linguagens de programação funcionais (como Scala), onde umEither
pode conter um valor de um tipo ou outro, mas não ambos. A única diferença é que nesses idiomas é idiomático colocar o erro no lado esquerdo e o valor no lado direito. Aqui está um artigo com mais informações .Não vi nenhuma resposta mencionando isso. Mas este exemplo seria uma maneira de evitar que uma exceção seja levantada para casos de falha conhecidos.
fonte