Denominar condições de várias linhas nas instruções 'if'? [fechadas]


674

Às vezes, quebro longas condições em ifs 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?


2
Se o seu editor usar o pacote pep8 Python para detectar quando avisar sobre violações do PEP8 , será necessário desativar o erro E125 ou encontrar uma solução de formatação que atenda aos pep8critérios do pacote. O pep8do 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.
akaihola

1
Observe que, para o primeiro exemplo, o pep8 lançará "E129 linha recuada visualmente com o mesmo recuo da próxima linha lógica".
Taylor Edmiston

Esta questão é muito antiga e tem muitas opiniões, mas é inequivocamente baseada em opiniões. A linguagem "não é muito atraente" e "não é muito bonita" estabelece os critérios de que a resposta supostamente correta é a que melhor se alinha à preferência estética dos solicitantes (ou seja, uma opinião). Eu poderia fazer exatamente a mesma pergunta e afirmar que não é uma duplicata porque meu gosto estético a qualifica como diferente e levará a uma resposta "correta" diferente.
Z4-tier

@ Nível Z4: sim, é baseado em opinião. Mas isso foi perguntado há 12 anos. SO era um lugar diferente e mais gentil na época. Recentemente, vem acumulando votos negativos desde que os padrões do SO mudaram. Ainda assim, tendo sido visto> 1 milhão de vezes, espero que esteja fazendo mais bem do que mal no mundo. Eu certamente posso ver pessoas se perguntando sobre a mesma pergunta hoje, pesquisando no Google, aterrissando nessa discussão e achando útil calibrar seu pensamento. Existem várias respostas altamente votadas para você escolher.
Eli Bendersky 30/04

@EliBendersky concorda completamente. É como se SO tivesse uma crise de identidade em andamento: embora claramente não se encaixe "nas regras" (o número de respostas válidas é uma prova disso), é igualmente claro que agrega valor. Sendo todas as coisas iguais, prefiro trabalhar com alguém que tenha desenvolvido pontos de vista articulados e fundamentados sobre o estilo de codificação, mesmo que seus pontos de vista sejam diferentes dos meus.
Z4-nível

Respostas:


747

Você não precisa usar 4 espaços em sua segunda linha condicional. Talvez use:

if (cond1 == 'val1' and cond2 == 'val2' and 
       cond3 == 'val3' and cond4 == 'val4'):
    do_something

Além disso, não esqueça que o espaço em branco é mais flexível do que você imagina:

if (   
       cond1 == 'val1' and cond2 == 'val2' and 
       cond3 == 'val3' and cond4 == 'val4'
   ):
    do_something
if    (cond1 == 'val1' and cond2 == 'val2' and 
       cond3 == 'val3' and cond4 == 'val4'):
    do_something

Ambos são bastante feios.

Talvez perca os colchetes (o Guia de estilo desencoraja isso)?

if cond1 == 'val1' and cond2 == 'val2' and \
   cond3 == 'val3' and cond4 == 'val4':
    do_something

Isso pelo menos lhe dá alguma diferenciação.

Ou até:

if cond1 == 'val1' and cond2 == 'val2' and \
                       cond3 == 'val3' and \
                       cond4 == 'val4':
    do_something

Eu acho que prefiro:

if cond1 == 'val1' and \
   cond2 == 'val2' and \
   cond3 == 'val3' and \
   cond4 == 'val4':
    do_something

Aqui está o Guia de estilo , que (desde 2010) recomenda o uso de colchetes.


45
Observe que as \ soluções finais não são recomendadas pelo PEP 8. Um motivo é que, se um espaço for adicionado por engano após a \, ele pode não aparecer no seu editor e o código se tornará sintaticamente incorreto.
Eric O Lebigot

14
Isso está errado, o guia de estilo diz "As linhas longas podem ser quebradas em várias linhas envolvendo expressões entre parênteses. Elas devem ser usadas preferencialmente ao uso de uma barra invertida para a continuação da linha". Você pode ver isso aqui: python.org/dev/peps/pep-0008/#maximum-line-length
joshcartme

8
@joshcartme O PEP foi alterado em hg.python.org/peps/rev/7a48207aaab6 para desencorajar explicitamente as barras invertidas. Vou atualizar a resposta.
Harley Holcombe

3
Obrigado, provavelmente é uma boa ideia atualizar seus exemplos também, pois agora eles não são recomendados. Eu estava tentando descobrir isso sozinho e fiquei confuso com a discrepância entre sua resposta e o guia de estilo (daí o meu comentário). Eu não estava apenas tentando ser pedante.
joshcartme

3
O PEP 8 agora desencoraja a quebra após ande iftambém.
Virtualxtc 11/0918

124

Eu recorri ao seguinte no caso degenerado, onde é simplesmente AND ou OR.

if all( [cond1 == 'val1', cond2 == 'val2', cond3 == 'val3', cond4 == 'val4'] ):

if any( [cond1 == 'val1', cond2 == 'val2', cond3 == 'val3', cond4 == 'val4'] ):

Ele raspa alguns caracteres e deixa claro que não há sutileza na condição.


4
Esta é uma abordagem interessante. Não aborda a questão das longas condições embora
Eli Bendersky

20
Tudo bem se você não se importa com curto-circuito.
Constantin

63
o curto-circuito nem sempre é rápido. Embora não seja boa prática de codificação, você pode ter um código como este existente: if destroy_world and DestroyTheWorld() == world_is_destroyed: .... Ótimo, agora você acabou de destruir o mundo por acidente. COMO VOCÊ PODE?
Aaron

3
Estou surpreso que isso tenha tantos votos positivos. Esta resposta ignora completamente a pergunta original sobre o estilo de condicionais de várias linhas .
Przemek D

2
Esta expressão não é preguiçosa. Portanto, não é equivalente se alguma condição de proteção estiver sendo seguida por uma falha possível.
Eugene-brilhante

56

Alguém tem que defender o uso do espaço em branco vertical aqui! :)

if (     cond1 == val1
     and cond2 == val2
     and cond3 == val3
   ):
    do_stuff()

Isso torna cada condição claramente visível. Também permite uma expressão mais limpa de condições mais complexas:

if (    cond1 == val1
     or 
        (     cond2_1 == val2_1
          and cond2_2 >= val2_2
          and cond2_3 != bad2_3
        )
   ):
    do_more_stuff()

Sim, estamos trocando um pouco de imóveis verticais por clareza. Vale a pena IMO.


19
Isso não parece ser bonito nem compatível com PEP8. O PEP8 diz que o local preferido para contornar um operador binário (por exemplo and, assim como or) é depois do operador, não antes dele.
Chris Medrela

7
@ChristopherMedrela diz a lógica por trás disso? Eu acho que colocar uma quebra de linha antes operador lógico é muito mais claro
Norill Tempest

4
Colocar o operador em primeiro lugar é bastante comum no mundo dos nós. A lógica é que notamos e lemos coisas à esquerda muito mais rapidamente do que coisas à direita - pelo menos nas culturas ocidentais. Muito válido em JavaScript, onde uma vírgula esquecida pode causar erros silenciosos.
tomekwi

11
Não faça isso por favor. Não apenas não é, PEP8como 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.
Urda

11
A partir da versão atual do PEP8, a quebra antes ou depois de um operador binário é considerada aceitável e antes que o operador seja considerado melhor para o novo código.
Soren Bjornstad 11/11

31

Prefiro esse estilo quando tenho uma condição if terrivelmente grande:

if (
    expr1
    and (expr2 or expr3)
    and hasattr(thingy1, '__eq__')
    or status=="HappyTimes"
):
    do_stuff()
else:
    do_other_stuff()

2
+1 para manter os recuos onde você pode acompanhá-los. Eu gosto de python e o uso muito, mas estou constantemente irritado por ser forçado a recuar. A multilinha realmente destrói a estética, mesmo quando bem feita.
Mightypile

4
Observe que ter seus operadores ande orno 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).
Mark Amery

8
a partir de 2016: 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).
cowbert

27

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:

def is_action__required(...):
    return (cond1 == 'val1' and cond2 == 'val2'
            and cond3 == 'val3' and cond4 == 'val4')

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.


23

Isso não melhora muito, mas ...

allCondsAreOK = (cond1 == 'val1' and cond2 == 'val2' and
                 cond3 == 'val3' and cond4 == 'val4')

if allCondsAreOK:
   do_something

1
Alternativa interessante. Mas 2 linhas extras :-)
Eli Bendersky

Wouldnt realmente funciona bem em um loop iterativo, o trabalho não tomaria com funções de fazer algo ... e para ser justo - feio
Mez

9
Brian, eu discordo parcialmente. O uso de variáveis ​​para resultados intermediários de um cálculo pode facilitar a compreensão do código e em um idioma compilado não terá nenhum impacto no desempenho. Provavelmente funcionaria em python, embora eu não usasse python se o desempenho fosse tão importante.
Mark Baker

1
@ MarkBaker Eu costumava concordar com o que você escreveu, até ler Martin Fowlers "Refatoração". Ele fornece um excelente argumento de que essas variáveis ​​intermediárias causam mais danos do que benefícios. Eles inibem a refatoração subsequente. Fazer sem eles leva a um estilo de programação mais funcional, que se presta bem à refatoração. Isso me surpreendeu, mas acredito que ele está certo, e desde então se esforçou para eliminar intermediários desnecessários como este do meu código - mesmo que sejam usados ​​mais de uma vez.
Jonathan Hartley

2
Bom, mas por que camelCase ?! :)
Leonid Shvechikov 17/03/2013

19

Sugiro mover a andpalavra-chave para a segunda linha e recuar todas as linhas que contêm condições com dois espaços em vez de quatro:

if (cond1 == 'val1' and cond2 == 'val2'
  and cond3 == 'val3' and cond4 == 'val4'):
    do_something

É 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.


9
Eu li em algum lugar no Gries ou no Djikstra que colocar o operador lógico na frente da linha - tornando mais visível - ajudou. E faço isso desde os anos 90. E isso ajuda.
8898 S.Lott

7
Observe que o Guia de estilo recomenda colocar a condicional no final da linha.
Harley Holcombe

3
Isso é verdade, embora eu nunca tenha concordado com isso. Afinal, é apenas um guia.
DzinX 10/10/08

8
O PEP8 não recomenda mais colocar o condicional no final da linha.
Soren Bjornstad 11/11

13

Parece citar PEP 0008 (guia de estilo oficial do Python), uma vez que comenta sobre esse assunto de maneira modesta:

Quando a parte condicional de uma ifinstrução-é longa o suficiente para exigir que ela seja escrita em várias linhas, vale a pena notar que a combinação de uma palavra-chave de dois caracteres (ou seja if), mais um único espaço, além de um parêntese de abertura cria um 4- natural. recuo de espaço para as linhas subseqüentes da condicional multilinha. Isso pode produzir um conflito visual com o conjunto de códigos recuado aninhado dentro da ifinstrução-, que também seria recuado naturalmente para 4 espaços. Esse PEP não assume posição explícita sobre como (ou se) distinguir visualmente essas linhas condicionais do conjunto aninhado dentro da ifdeclaração. As opções aceitáveis ​​nessa situação incluem, mas não estão limitadas a:

# No extra indentation.
if (this_is_one_thing and
    that_is_another_thing):
    do_something()

# Add a comment, which will provide some distinction in editors
# supporting syntax highlighting.
if (this_is_one_thing and
    that_is_another_thing):
    # Since both conditions are true, we can frobnicate.
    do_something()

# Add some extra indentation on the conditional continuation line.
if (this_is_one_thing
        and that_is_another_thing):
    do_something()

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.


+1 para PEP8. Isso deve ser aceito, pois é (na prática) o guia oficial de estilo do Python.
Michael - Onde está Clay Shirky

2
Também é importante enfatizar que, o PEP8 declara explicitamente sua posição, já que este PEP não assume posição explícita sobre como (ou se) distinguir visualmente essas linhas condicionais do conjunto aninhado dentro da declaração if. As opções aceitáveis ​​nessa situação incluem, mas não estão limitadas a: ... (cortadas) Então, pare de discutir, vá com algo que você gosta!
RayLuo # 14/16

7

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.

condition = [cond1 == 'val1', cond2 == 'val2', cond3 == 'val3', cond4 == 'val4']

if all(condition):
   do_something

4

Estou surpreso por não ver minha solução preferida,

if (cond1 == 'val1' and cond2 == 'val2'
    and cond3 == 'val3' and cond4 == 'val4'):
    do_something

Como andé uma palavra-chave, ela é destacada pelo meu editor e parece suficientemente diferente da do_something abaixo dela.


Mas a linha de continuação ainda não se distingue da próxima linha lógica ...
Chris Medrela 25/10

1
Observe que esta é uma violação do PEP 0008 ( "O local preferido para contornar um operador binário é após o operador, não antes dele" ). Se você se importa, é claro, depende de você.
Mark Amery

1
Aliás, essa não é mais a minha solução preferida. ;)
Marius Gedminas

4

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".

conditions_met = (
    cond1 == 'val1' 
    and cond2 == 'val2' 
    and cond3 == 'val3' 
    and cond4 == 'val4'
    )
if conditions_met:
    do_something

Se as condições precisarem ser avaliadas mais de uma vez, como em um whileloop, é melhor usar uma função local.


1
Além disso, você pode declarar uma função ou um lambda para retornar seu verdadeiro false, em vez de criar uma variável extra.
Techdragon # 5/13

@Techdragon se as condições estiverem em outro lugar, colocá-las em um bloco lambda exigiria que o bloco lambda fosse nomeado para que possa ser referenciado posteriormente na condição if. Se um lambda será nomeado, por que não uma função regular, afinal? Eu pessoalmente gosto dessa expressão booleana reduzida.
Sri Kadimisetty

Eu concordo, e é por isso que normalmente usaria uma função na maioria dos casos, para melhorar a legibilidade e facilitar a digestão mental ao navegar para entender o fluxo de controle do programa. Mencionei o lambda para garantir que a opção 'menor' também esteja presente, caso as pessoas tenham consciência do espaço.
Techdragon

4

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 ..."

if not user.isAdmin() and user.isTeacher() and not user.isStudent():
    doSomething()

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:

displayTeacherPanel = not user.isAdmin() and user.isTeacher() and not user.isStudent()
if displayTeacherPanel:
    showTeacherPanel()

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:

if displayTeacherPanel or user.canSeeSpecialPanel():
    showSpecialPanel()

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).


3

"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:

def c1():
    print " Executed c1"
    return False
def c2():
    print " Executed c2"
    return False


print "simple and (aborts early!)"
if c1() and c2():
    pass

print

print "all (executes all :( )"
if all((c1(),c2())):
    pass

print

5
Incorreta! Eles só fazem porque você faz. Tente tudo (f () para f em [c1, c2]).
habnabit

2
Eu acho que ele estava usando funções apenas como exemplo, porque ele pode facilmente fazê-las imprimir alguma coisa. Se considerarmos uma série de expressões arbitrárias fornecidas em uma lista até all()então, a menos que você as envolva em uma lambda e use seu f()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.
Brandon Rhodes

3

(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.)

if (cond1 == "val1" and cond22 == "val2"
and cond333 == "val3" and cond4444 == "val4"):
    do_something

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:

if (cond1 == "val1" and cond22 == "val2"
and cond333 == "val3" and cond4444 == "val4") {
    do_something
}

3

Puro e simples, também passa nas verificações do pep8:

if (
    cond1 and
    cond2
):
    print("Hello World!")

Nos últimos tempos, tenho preferido as funções alle any, 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:

if all([
    cond1,
    cond2,
]):
    print("Hello World!")

Lembre-se de passar em um único iterável! Passar N-argumentos não está correto.

Nota: anyé como muitas orcomparações, allé como muitas andcomparações.


Isso combina muito bem com a compreensão do gerador, por exemplo:

# Check if every string in a list contains a substring:
my_list = [
    'a substring is like a string', 
    'another substring'
]

if all('substring' in item for item in my_list):
   print("Hello World!")

# or

if all(
    'substring' in item
    for item in my_list
):
    print("Hello World!")

Mais sobre: compreensão de geradores


1
Devo também salientar que a configuração de estoque do pylint deseja um recuo de entrada na continuação da linha no if; o que me dissuadiu de usar esse esquema.
ThorSummoner

2

E se apenas inserirmos uma linha em branco adicional entre a condição e o corpo e fizermos o resto da maneira canônica?

if (cond1 == 'val1' and cond2 == 'val2' and
    cond3 == 'val3' and cond4 == 'val4'):

    do_something

ps Eu sempre uso guias, não espaços; Não consigo afinar ...


3
Isso seria muito confuso, especialmente quando o corpo do condicional é longo, eu acho.
Eli Bendersky

Concordo com Eli, o encapsulamento e o recuo aqui são confusos para longas filas. Além disso, a nova regra é que os ande ordeclarações devem começar na próxima linha
virtualxtc

2

O que eu costumo fazer é:

if (cond1 == 'val1' and cond2 == 'val2' and
    cond3 == 'val3' and cond4 == 'val4'
   ):
    do_something

Dessa forma, a chave de fechamento e o cólon marcam visualmente o fim de nossa condição.


1
Quase correto; O PEP 8 agora recomenda a quebra antes do andor or.
Virtualxtc 11/0918

2

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

condition = random.randint(0, 100) # to demonstrate
anti_conditions = [42, 67, 12]
if condition not in anti_conditions:
    pass

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.


esta é realmente uma maneira muito elegante de fazer multi-condicionais :) não sei por que não tem mais votos :), existem algumas ressalvas?
22318 dim_user

@SaulCruz realmente não existe Não apenas a variável de condição não precisa ser repetida, você também economiza nas muitas duplicatas da verificação de cada valor, isso simplesmente coloca apenas os valores em uma matriz e permite que o mecanismo faça seu trabalho (otimizado) verificar a condição para você
Stoff

@Stoff Obrigado por remover meu comentário. Queria ressaltar que sua abordagem não responde à pergunta do OP. O código que você fornece não pode ser aplicado ao código na pergunta. Se você pensa o contrário, deve adicionar o código do OP reformatado pela sua abordagem para provar seu ponto de vista.
Jeyekomon 06/06

Não é a resposta aceita, no entanto, é claramente uma abordagem alternativa (outros concordam). Então, encorajamos respostas alternativas, então qual é o argumento exatamente? Seja claro em sua própria pergunta, talvez considere abrir sua própria pergunta se precisar da atenção adequada. Ps eu não sou um mod SO, eu não posso remover comentários
Stoff

2

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.

conditions = [1, 2, 3, 4]
values = [1, 2, 3, 4]
if all([c==v for c, v in zip(conditions, values)]):
    # do something

Se eu quisesse codificar uma declaração como essa, escreveria assim para legibilidade:

if (condition1==value1) and (condition2==value2) and \
   (condition3==value3) and (condition4==value4):

E apenas para lançar outra solução com um iandoperador :

proceed = True
for c, v in zip(conditions, values):
    proceed &= c==v

if proceed:
    # do something

1
Apenas por diversão: all(map(eq, have, expected)). (with from operator import eq)
Gabriel Garcia

1

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:

>>> x = {'cond1' : 'val1', 'cond2' : 'val2'}
>>> y = {'cond1' : 'val1', 'cond2' : 'val2'}
>>> x == y
True

Essa opção é mais complicada, mas você também pode achar útil:

class Klass(object):
    def __init__(self, some_vars):
        #initialize conditions here
    def __nonzero__(self):
        return (self.cond1 == 'val1' and self.cond2 == 'val2' and
                self.cond3 == 'val3' and self.cond4 == 'val4')

foo = Klass()
if foo:
    print "foo is true!"
else:
    print "foo is false!"

Não sei se isso funciona para você, mas é outra opção a considerar. Aqui está mais uma maneira:

class Klass(object):
    def __init__(self):
        #initialize conditions here
    def __eq__(self):
        return (self.cond1 == 'val1' and self.cond2 == 'val2' and
               self.cond3 == 'val3' and self.cond4 == 'val4')

x = Klass(some_values)
y = Klass(some_other_values)
if x == y:
    print 'x == y'
else:
    print 'x!=y'

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.)


1

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).

if bool(condition1 and
        condition2 and
        ...
        conditionN):
    foo()
    bar()

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:

if (((foo and
      bar and
      frob and
      ninja_bear))):
    do_stuff()

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 :)


1

Você pode dividi-lo em duas linhas

total = cond1 == 'val' and cond2 == 'val2' and cond3 == 'val3' and cond4 == val4
if total:
    do_something()

Ou mesmo adicione uma condição de cada vez. Dessa forma, pelo menos separa a desordem da if.


1

Eu sei que esse segmento é antigo, mas tenho algum código Python 2.7 e o PyCharm (4.5) ainda reclama sobre este caso:

if foo is not None:
    if (cond1 == 'val1' and cond2 == 'val2' and
        cond3 == 'val3' and cond4 == 'val4'):
            # some comment about do_something
            do_something

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 ...


0

Coloque suas condições em uma lista e depois faça o que quiser. gostar:

if False not in Conditions:
    do_something

0

Acho que, quando tenho condições longas, geralmente tenho um corpo de código curto. Nesse caso, apenas recuo duas vezes o corpo, assim:

if (cond1 == 'val1' and cond2 == 'val2' and
    cond3 == 'val3' and cond4 == 'val4'):
        do_something

1
@qarma, você gostaria de expandir? É certamente melhor do que o uso de caracteres de continuação de linha, que são recomendados contra pelo PEP 8
xorsyst

Este é de fato um caso válido para continuação de linha. Parênteses da IMPO significam uma tupla ou uma chamada de função. O uso do OP é muito parecido com o C, prefiro a sintaxe python sempre que possível. Eu admito que \ não é universalmente favorecido.
Dima Tisnek

0
  if cond1 == 'val1' and \
     cond2 == 'val2' and \
     cond3 == 'val3' and \
     cond4 == 'val4':
      do_something

ou se isso for mais claro:

  if cond1 == 'val1'\
     and cond2 == 'val2'\
     and cond3 == 'val3'\
     and cond4 == 'val4':
      do_something

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


O guia do Google também fornece um exemplo de uma condição complexa , que corresponde à "maneira mais óbvia de fazer isso", conforme mencionado pelo OP. Embora o guia não defenda explicitamente a formatação longa, “se” é assim.
Anton Strogonoff 08/04

0

Aqui está outra abordagem:

cond_list = ['cond1 == "val1"','cond2=="val2"','cond3=="val3"','cond4=="val4"']
if all([eval(i) for i in cond_list]):
 do something

Isso também facilita a adição de outra condição facilmente, sem alterar a instrução if, simplesmente anexando outra condição à lista:

cond_list.append('cond5=="val5"')

0

Eu costumo usar:

if ((cond1 == 'val1' and cond2 == 'val2' and
     cond3 == 'val3' and cond4 == 'val4')):
    do_something()

0

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.

#!/usr/bin/python
import sys
numberOfArgument =len(sys.argv)
weblogic_username =''
weblogic_password = ''
weblogic_admin_server_host =''
weblogic_admin_server_port =''


if numberOfArgument == 5:
        weblogic_username = sys.argv[1]
        weblogic_password = sys.argv[2]
        weblogic_admin_server_host =sys.argv[3]
        weblogic_admin_server_port=sys.argv[4]
elif numberOfArgument <5:
        print " weblogic UserName, weblogic Password and weblogic host details are Mandatory like, defalutUser, passwordForDefaultUser, t3s://server.domainname:7001 ."
        weblogic_username = raw_input("Enter Weblogic user Name")
        weblogic_password = raw_input('Enter Weblogic user Password')
        weblogic_admin_server_host = raw_input('Enter Weblogic admin host ')
        weblogic_admin_server_port = raw_input('Enter Weblogic admin port')
#enfelif
#endIf

0

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:

  1. Os meus valores parecem estranhos para alguém que pode tentar decifrar o script.
  2. A manutenção do código terá um custo alto, se esses valores forem alterados (o mais provável) ou se novas condições forem adicionadas (esquema quebrado)

Para ignorar todos esses problemas, seu script deve ser assim

param_Val01 = Value 01   #give a meaningful name for param_Val(i) preferable an integer
param_Val02 = Value 02
param_Val03 = Value 03
param_Val04 = Value 04   # and ... etc

conditions = 0           # this is a value placeholder

########
Add script that if true will make:

conditions = conditions + param_Val01   #value of placeholder is updated
########

### repeat as needed


if conditions = param_Val01 + param_Val02 + param_Val03 + param_Val04:
    do something

Prós deste método:

  1. Script é legível.

  2. O script pode ser facilmente mantido.

  3. conditions é uma operação de comparação com uma soma de valores que representa as condições desejadas.
  4. Não há necessidade de condições multiníveis

Espero que ajude a todos

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.