Qual é a melhor prática em uma função definida pelo usuário em Python: raise
uma exceção ou return None
? Por exemplo, tenho uma função que localiza o arquivo mais recente em uma pasta.
def latestpdf(folder):
# list the files and sort them
try:
latest = files[-1]
except IndexError:
# Folder is empty.
return None # One possibility
raise FileNotFoundError() # Alternative
else:
return somefunc(latest) # In my case, somefunc parses the filename
Outra opção é deixar a exceção e tratá-la no código do chamador, mas acho que é mais claro lidar com um do FileNotFoundError
que com um IndexError
. Ou é incorreto levantar novamente uma exceção com um nome diferente?
python
exception-handling
parcydarks
fonte
fonte
Respostas:
É realmente uma questão de semântica. O que isso
foo = latestpdf(d)
significa ?É perfeitamente razoável que não haja um arquivo mais recente? Então, claro, basta retornar Nenhum.
Você espera encontrar sempre um arquivo mais recente? Crie uma exceção. E sim, levantar novamente uma exceção mais apropriada é bom.
Se esta for apenas uma função geral que deve ser aplicada a qualquer diretório, eu faria a primeira e retornaria Nenhum. Se o diretório for, por exemplo, destinado a ser um diretório de dados específico que contém um conjunto de arquivos conhecido de um aplicativo, eu levantaria uma exceção.
fonte
None
.Gostaria de fazer algumas sugestões antes de responder à sua pergunta, pois pode responder à pergunta para você.
latestpdf
significa muito pouco para qualquer pessoa, mas examinar sua funçãolatestpdf()
obtém o pdf mais recente. Eu sugiro que você nomeiegetLatestPdfFromFolder(folder)
.Assim que fiz isso ficou claro o que deveria retornar .. Se não houver um pdf levante uma exceção. Mas espere aí mais ..
for folder in folders: try: latest = getLatestPdfFromFolder(folder) results = somefuc(latest) except IOError: pass
Espero que isto ajude!
fonte
get_latest_pdf_from_folder
. Na verdade, Pep8: "Os nomes das funções devem ser minúsculos, com palavras separadas por sublinhados conforme necessário para melhorar a legibilidade."Eu geralmente prefiro lidar com exceções internamente (ou seja, tente / exceto dentro da função chamada, possivelmente retornando um Nenhum) porque o python é digitado dinamicamente. Em geral, considero um julgamento de uma forma ou de outra, mas em uma linguagem digitada dinamicamente, existem pequenos fatores que inclinam a balança a favor de não passar a exceção para o chamador:
if val is None
é um pouco mais fácil do queexcept ComplicatedCustomExceptionThatHadToBeImportedFromSomeNameSpace
. Sério, eu odeio ter que lembrar de digitarfrom django.core.exceptions import ObjectDoesNotExist
no topo de todos os meus arquivos django apenas para lidar com um caso de uso realmente comum. Em um mundo com tipagem estática, deixe o editor fazer isso por você.Honestamente, porém, é sempre uma chamada de julgamento, e a situação que você está descrevendo, em que a função chamada recebe um erro que não pode ajudar, é um excelente motivo para levantar novamente uma exceção que seja significativa. Você tem a ideia exata, mas a menos que seja uma exceção, fornecerá informações mais significativas em um rastreamento de pilha do que
AttributeError: 'NoneType' object has no attribute 'foo'
que, nove em dez vezes, é o que o chamador verá se você retornar um Nenhum não atendido, não se preocupe.
(Tudo isso me faz desejar que as exceções python tivessem os
cause
atributos por padrão, como em java, o que permite passar exceções em novas exceções para que você possa relançar tudo o que quiser e nunca perder a fonte original do problema.)fonte
com a digitação do python 3.5 :
função de exemplo ao retornar None será:
def latestpdf(folder: str) -> Union[str, None]
e ao levantar uma exceção será:
def latestpdf(folder: str) -> str
a opção 2 parece mais legível e pythônica
(+ opção para adicionar comentário à exceção conforme indicado anteriormente.)
fonte
Union[str, None]
deveria serOptional[str]
Em geral, eu diria que uma exceção deve ser lançada se algo catastrófico ocorreu e não pode ser recuperado (ou seja, sua função lida com algum recurso da Internet que não pode ser conectado), e você deve retornar None se sua função realmente deve retornar algo mas nada seria apropriado retornar (ou seja, "Nenhum" se sua função tentar corresponder a uma substring em uma string, por exemplo).
fonte