Às vezes, quebro longas condições em if
s em várias linhas. A maneira mais óbvia de fazer isso é:
if (cond1 == 'val1' and cond2 == 'val2' and
cond3 == 'val3' and cond4 == 'val4'):
do_something
Não é muito atraente visualmente, porque a ação combina com as condições. No entanto, é o caminho natural, usando o recuo Python correto de 4 espaços.
No momento estou usando:
if ( cond1 == 'val1' and cond2 == 'val2' and
cond3 == 'val3' and cond4 == 'val4'):
do_something
Mas isso não é muito bonito. :-)
Você pode recomendar uma maneira alternativa?
python
coding-style
if-statement
Eli Bendersky
fonte
fonte
pep8
critérios do pacote. Opep8
do pacote de edição # 126 é sobre a fixação do pacote de seguir rigorosamente a especificação PEP8. A discussão para a edição inclui algumas sugestões de estilo também vistas aqui.Respostas:
Você não precisa usar 4 espaços em sua segunda linha condicional. Talvez use:
Além disso, não esqueça que o espaço em branco é mais flexível do que você imagina:
Ambos são bastante feios.
Talvez perca os colchetes (o Guia de estilo desencoraja isso)?
Isso pelo menos lhe dá alguma diferenciação.
Ou até:
Eu acho que prefiro:
Aqui está o Guia de estilo , que (desde 2010) recomenda o uso de colchetes.
fonte
and
eif
também.Eu recorri ao seguinte no caso degenerado, onde é simplesmente AND ou OR.
Ele raspa alguns caracteres e deixa claro que não há sutileza na condição.
fonte
if destroy_world and DestroyTheWorld() == world_is_destroyed: ...
. Ótimo, agora você acabou de destruir o mundo por acidente. COMO VOCÊ PODE?Alguém tem que defender o uso do espaço em branco vertical aqui! :)
Isso torna cada condição claramente visível. Também permite uma expressão mais limpa de condições mais complexas:
Sim, estamos trocando um pouco de imóveis verticais por clareza. Vale a pena IMO.
fonte
and
, assim comoor
) é depois do operador, não antes dele.PEP8
como torna mais difícil determinar a operação lógica com a qual você está encadeando. Eu reprovaria isso se chegasse à minha mesa através da revisão de código.Prefiro esse estilo quando tenho uma condição if terrivelmente grande:
fonte
and
eor
no início da linha viola o PEP 0008 , que declara "O local preferido para contornar um operador binário é depois do operador, não antes dele". . Porém, eu gosto de ter o colchete e os dois pontos em sua própria linha para separar a condição if do corpo (e é perfeitamente possível fazer isso mantendo os operadores booleanos no final da linha para conformidade com PEP-0008).For decades the recommended style was to break after binary operators. But this can hurt readability in two ways
...In Python code, it is permissible to break before or after a binary operator, as long as the convention is consistent locally. For new code Knuth's style is suggested.
(o estilo de Knuth é iniciar a linha com o operador).Aqui está minha opinião pessoal: condições longas são (na minha opinião) um cheiro de código que sugere refatorar para uma função / método de retorno booleano. Por exemplo:
Agora, se eu encontrasse uma maneira de fazer com que as condições de várias linhas parecessem boas, provavelmente me contentaria em tê-las e pularia a refatoração.
Por outro lado, tê-los perturbando meu senso estético atua como um incentivo à refatoração.
Minha conclusão, portanto, é que várias condições de linha devem parecer feias e isso é um incentivo para evitá-las.
fonte
Isso não melhora muito, mas ...
fonte
Sugiro mover a
and
palavra-chave para a segunda linha e recuar todas as linhas que contêm condições com dois espaços em vez de quatro:É exatamente assim que eu resolvo esse problema no meu código. Ter uma palavra-chave como a primeira palavra na linha torna a condição muito mais legível e a redução do número de espaços distingue ainda mais a condição da ação.
fonte
Parece citar PEP 0008 (guia de estilo oficial do Python), uma vez que comenta sobre esse assunto de maneira modesta:
Observe o "não limitado a" na citação acima; além das abordagens sugeridas no guia de estilo, algumas das sugeridas em outras respostas a essa pergunta também são aceitáveis.
fonte
Aqui está o que eu faço, lembre-se de que "todos" e "qualquer" aceitam uma iterável, então apenas coloquei uma condição longa em uma lista e deixei que "todos" fizessem o trabalho.
fonte
Estou surpreso por não ver minha solução preferida,
Como
and
é uma palavra-chave, ela é destacada pelo meu editor e parece suficientemente diferente da do_something abaixo dela.fonte
Além do que @krawyoti disse ... As condições longas cheiram porque são difíceis de ler e difíceis de entender. O uso de uma função ou variável torna o código mais claro. No Python, prefiro usar o espaço vertical, colocar parênteses e colocar os operadores lógicos no início de cada linha para que as expressões não pareçam "flutuantes".
Se as condições precisarem ser avaliadas mais de uma vez, como em um
while
loop, é melhor usar uma função local.fonte
Pessoalmente, gosto de adicionar significado a longas declarações if. Eu precisaria pesquisar no código para encontrar um exemplo apropriado, mas aqui está o primeiro exemplo que vem à mente: digamos que eu tenha uma lógica peculiar, na qual desejo exibir uma determinada página, dependendo de muitas variáveis.
Inglês: "Se o usuário logado NÃO for um professor administrador, mas apenas um professor regular e não for um aluno ..."
Claro que isso pode parecer bom, mas ler essas instruções if é muito trabalhoso. Que tal atribuirmos a lógica ao rótulo que faz sentido. O "rótulo" é realmente o nome da variável:
Isso pode parecer bobagem, mas você pode ter outra condição em que SOMENTE deseja exibir outro item se, e somente se, estiver exibindo o painel do professor OU se o usuário tiver acesso a esse outro painel específico por padrão:
Tente escrever a condição acima sem usar variáveis para armazenar e rotular sua lógica, e você não apenas terá uma declaração lógica muito confusa e difícil de ler, mas também se repetirá. Embora existam exceções razoáveis, lembre-se: Não se repita (DRY).
fonte
"all" e "any" são bons para as muitas condições do mesmo tipo de caso. MAS eles sempre avaliam todas as condições. Como mostrado neste exemplo:
fonte
all()
então, a menos que você as envolva em uma lambda e use seuf()
truque, todas elas serão avaliadas. Em outras palavras, Aaron: acho que Anders estava tentando falar sobre condições em geral, usando callables como um exemplo específico; mas sua réplica se aplica apenas a funções.(Modifiquei levemente os identificadores, pois os nomes de largura fixa não são representativos do código real - pelo menos, não o código real que encontro - e desmente a legibilidade de um exemplo.)
Isso funciona bem para "e" e "ou" (é importante que eles sejam os primeiros na segunda linha), mas muito menos para outras condições longas. Felizmente, o primeiro parece ser o caso mais comum, enquanto o último é frequentemente reescrito com uma variável temporária. (Geralmente não é difícil, mas pode ser difícil ou muito menos óbvio / legível para preservar o curto-circuito de "e" / "ou" ao reescrever.)
Desde que encontrei esta pergunta em seu post sobre C ++ , incluirei que meu estilo C ++ é idêntico:
fonte
Puro e simples, também passa nas verificações do pep8:
Nos últimos tempos, tenho preferido as funções
all
eany
, uma vez que raramente misturo as comparações And e Or, isso funciona bem e tem a vantagem adicional de Failing Early com a compreensão dos geradores:Lembre-se de passar em um único iterável! Passar N-argumentos não está correto.
Nota:
any
é como muitasor
comparações,all
é como muitasand
comparações.Isso combina muito bem com a compreensão do gerador, por exemplo:
Mais sobre: compreensão de geradores
fonte
E se apenas inserirmos uma linha em branco adicional entre a condição e o corpo e fizermos o resto da maneira canônica?
ps Eu sempre uso guias, não espaços; Não consigo afinar ...
fonte
and
eor
declarações devem começar na próxima linhaO que eu costumo fazer é:
Dessa forma, a chave de fechamento e o cólon marcam visualmente o fim de nossa condição.
fonte
and
oror
.Todos os entrevistados que também fornecem condicionais para a declaração if são tão feios quanto o problema apresentado. Você não resolve esse problema fazendo o mesmo ..
Até a resposta do PEP 0008 é repulsiva.
Aqui está uma abordagem muito mais legível
Quer que eu coma minhas palavras? Convença-me de que você precisa de vários condicionais e eu literalmente imprimo e comerei para sua diversão.
fonte
Eu acho que a solução do @ zkanda seria boa com uma pequena reviravolta. Se você tivesse suas condições e valores em suas próprias listas respectivas, poderia usar uma compreensão da lista para fazer a comparação, o que tornaria as coisas um pouco mais gerais para adicionar pares de condição / valor.
Se eu quisesse codificar uma declaração como essa, escreveria assim para legibilidade:
E apenas para lançar outra solução com um
iand
operador :fonte
all(map(eq, have, expected))
. (withfrom operator import eq
)Apenas algumas outras idéias aleatórias por uma questão de integridade. Se eles funcionarem para você, use-os. Caso contrário, você provavelmente está melhor tentando outra coisa.
Você também pode fazer isso com um dicionário:
Essa opção é mais complicada, mas você também pode achar útil:
Não sei se isso funciona para você, mas é outra opção a considerar. Aqui está mais uma maneira:
Os dois últimos que eu não testei, mas os conceitos devem ser suficientes para você continuar, se é isso que você quer seguir.
(E, para que conste, se isso é apenas uma coisa única, você provavelmente está melhor usando o método que você apresentou a princípio. Se você estiver fazendo a comparação em vários locais, esses métodos podem melhorar a legibilidade o suficiente para facilitar a leitura. você não se sente tão mal pelo fato de serem meio hacky.)
fonte
Eu também tenho lutado para encontrar uma maneira decente de fazer isso, então tive uma idéia (não uma bala de prata, já que isso é principalmente uma questão de gosto).
Encontro alguns méritos nessa solução em comparação com outros que já vi, ou seja, você obtém exatamente 4 espaços extras de recuo (bool), permitindo que todas as condições se alinhem verticalmente, e o corpo da instrução if pode ser recuado uma maneira clara (ish). Isso também mantém os benefícios da avaliação de curto-circuito de operadores booleanos, mas é claro que adiciona a sobrecarga de uma chamada de função que basicamente não faz nada. Você poderia argumentar (validamente) que qualquer função retornando seu argumento poderia ser usada aqui em vez de bool, mas, como eu disse, é apenas uma ideia e, em última análise, é uma questão de gosto.
Engraçado o bastante, enquanto escrevia isso e pensava no "problema", tive outra idéia, que remove a sobrecarga de uma chamada de função. Por que não indicar que estamos prestes a entrar em uma condição complexa usando pares extras de parênteses? Diga mais 2, para dar um bom recuo de 2 espaços nas sub-condições em relação ao corpo da instrução if. Exemplo:
Eu meio que gosto disso porque quando você olha para ele, um sino toca imediatamente em sua cabeça dizendo "ei, há uma coisa complexa acontecendo aqui!" . Sim, eu sei que parênteses não ajudam na legibilidade, mas essas condições devem aparecer raramente o suficiente, e quando elas aparecerem, você precisará parar e lê-las com cuidado de qualquer maneira (porque são complexas ).
Enfim, apenas mais duas propostas que não vi aqui. Espero que isso ajude alguém :)
fonte
Você pode dividi-lo em duas linhas
Ou mesmo adicione uma condição de cada vez. Dessa forma, pelo menos separa a desordem da
if
.fonte
Eu sei que esse segmento é antigo, mas tenho algum código Python 2.7 e o PyCharm (4.5) ainda reclama sobre este caso:
Mesmo com o aviso PEP8 "linha recuada visualmente com o mesmo recuo da próxima linha lógica", o código real está completamente OK? Não é "recuar demais"?
... há momentos em que eu gostaria que o Python tivesse mordido a bala e acabado de usar chaves. Gostaria de saber quantos erros foram introduzidos acidentalmente ao longo dos anos devido a erros de identificação acidental ...
fonte
Coloque suas condições em uma lista e depois faça o que quiser. gostar:
fonte
Acho que, quando tenho condições longas, geralmente tenho um corpo de código curto. Nesse caso, apenas recuo duas vezes o corpo, assim:
fonte
ou se isso for mais claro:
Não há motivo para que o recuo deva ser um múltiplo de 4 nesse caso, por exemplo, consulte "Alinhado ao delimitador de abertura":
http://google-styleguide.googlecode.com/svn/trunk/pyguide.html?showone=Indentation#Indentation
fonte
Aqui está outra abordagem:
Isso também facilita a adição de outra condição facilmente, sem alterar a instrução if, simplesmente anexando outra condição à lista:
fonte
Eu costumo usar:
fonte
se a nossa condição if & an else precisar executar várias instruções dentro dela, podemos escrever como abaixo. A cada momento, temos outro exemplo com uma declaração dentro dela.
Obrigado, funciona para mim.
fonte
Perdoe meu noobness, mas acontece que não conheço o #Python como qualquer um de vocês aqui, mas acontece que encontrei algo semelhante ao criar scripts para meus próprios objetos em uma modelagem 3D BIM, então adaptarei meu algoritmo a o do python.
O problema que encontro aqui é de dupla face:
Para ignorar todos esses problemas, seu script deve ser assim
Prós deste método:
Script é legível.
O script pode ser facilmente mantido.
Espero que ajude a todos
fonte