Pergunta

Às vezes eu quebrar condições longos 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, muito visualmente atraente, porque as misturas de ação com as condições. No entanto, é a maneira natural com recuo Python correta de 4 espaços.

No momento eu 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?

Foi útil?

Solução

Você não precisa usar 4 espaços na 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 se esqueça 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 os são bastante feio embora.

Talvez perder os suportes ( Estilo desencoraja este embora)?

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

Esta, pelo menos, dá-lhe alguma diferenciação.

Ou mesmo:

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

Eu acho que eu prefiro:

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

Aqui está o Estilo, que ( desde 2010) recomenda o uso de parênteses.

Outras dicas

Eu já recorreu ao seguinte no caso degenerado onde é simples e é 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 personagens e deixa claro que não há nenhuma sutileza à condição.

Alguém tem que usar campeão de espaços em branco verticais aqui! :)

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

Isso faz com que cada condição claramente visível. Ele também permite a 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 para maior clareza. pena Bem, IMO.

Aqui é a minha opinião muito pessoal: condições longas são (na minha opinião) um cheiro de código que sugere refatoração em uma função / método retornando boolean. Por exemplo:

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

Agora, se eu encontrei uma maneira de tornar as condições de várias linhas com bom aspecto, eu provavelmente iria encontrar-me contente com ter-los e ignorar o refactoring.

Por outro lado, tendo-lhes perturbar o meu senso estético atua como um incentivo para refatoração.

A minha conclusão, portanto, é que várias condições da linha deve olhar feio e isso é um incentivo para evitá-los.

Esta não melhorar muito, mas ...

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

if allCondsAreOK:
   do_something

Eu prefiro este estilo quando tenho uma terrivelmente grande se-condição:

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

Eu sugiro mover a palavra-chave and para a segunda linha e recuo de 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

Este é exatamente como eu resolver este problema no meu código. Ter uma palavra-chave como a primeira palavra na linha torna a condição muito mais legível, e reduzindo o número de espaços mais distingue condição da ação.

Parece pena citar PEP 0008 (guia oficial estilo de Python), uma vez que comenta sobre esta questão longamente modesta:

Quando a parte condicional de uma -Declaração if é longa o suficiente para exigir que ele seja escrito em várias linhas, vale a pena notar que a combinação de uma palavra-chave de dois caracteres (ou seja if), além de um único espaço, além de um parêntese de abertura cria um travessão 4-espaço natural para as linhas subsequentes do condicional de várias linhas. Isso pode produzir um conflito visual com a suíte recuado de código aninhada dentro da -Declaração if, o que também, naturalmente, ser recuado para 4 espaços. Este PEP não toma posição explícita em como (ou se) para mais distinguir visualmente tais linhas condicional do conjunto aninhado no interior do -Declaração if. opções aceitáveis ??nesta situação incluem, mas não estão limitados 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, alguns dos mais sugeridas em outras respostas para essa pergunta é aceitável também.

Aqui está o que eu faço, lembre-se que "todos" e "qualquer" aceita um iterável, então eu só colocar uma condição muito tempo em uma lista e deixe "todos" fazer o trabalho.

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

if all(condition):
   do_something

Estou surpreso de não ver a minha solução preferida,

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

Desde and é uma palavra-chave, que é realçada pelo meu editor, e aparência suficientemente diferentes do do_something abaixo.

Pessoalmente, eu gostaria de acrescentar significado às declarações if-longa. Eu teria que procurar através de código para encontrar um exemplo apropriado, mas aqui está o primeiro exemplo que vem à mente:. Digamos que eu acontecer a correr em alguma lógica peculiar onde eu quero exibir uma determinada página, dependendo de muitas variáveis ??

Inglês: "Se o usuário conectado não é um professor administrador, mas é apenas um professor regular, e não é um estudante de si mesmos ..."

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

Claro que isso pode parecer bom, mas lendo as instruções se é um monte de trabalho. Que tal nós atribuímos a lógica de etiqueta que faz sentido. O "rótulo" é na verdade 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 ainda uma outra condição em que você só quer exibir outro item se, e somente se, você está exibindo o painel de professor ou se o usuário tem acesso a esse outro painel específico por padrão:

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

Tente escrever a condição acima sem o uso de variáveis ??para armazenar e rotular sua lógica, e não só você acabar com um muito confuso, difícil de ler a declaração lógico, mas você também apenas repetiu-se. Embora haja exceções razoáveis, lembre-se:. Do not Repeat Yourself (DRY)

"todos" e "qualquer" são agradáveis ??para as muitas condições de mesmo caso tipo. Mas sempre avalia 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

(Eu levemente modificado os identificadores como nomes de largura fixa não são representativos do verdadeiro código - pelo menos não é real código que eu encontro -. E desmentem 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 estão em primeiro lugar na segunda linha), mas muito menos para outras condições longos. Felizmente, o ex parece ser o caso mais comum, enquanto os últimos são muitas vezes facilmente reescrito com uma variável temporária. (É geralmente não é difícil, mas pode ser difícil ou muito menos óbvia / legível para preservar o curto-circuito de "e" / "ou" quando reescrevendo.)

Desde que eu encontrei esta pergunta de seu blog sobre C ++ , vou incluir esse estilo meu C ++ é idêntico:

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

Adicionando ao que @krawyoti disse ... condições longas cheiro, porque eles são difíceis de ler e difícil de entender. Utilizando uma função ou uma variável faz com que o código mais claro. Em Python, eu prefiro usar o espaço vertical, parêntese encerram, e coloque os operadores lógicos no início de cada linha de modo que as expressões não se parecem com "flutuante".

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

Se as condições precisam ser avaliados mais de uma vez, como em um loop while, em seguida, usando uma função local é melhor.

Puro e simples, também passa cheques pep8:

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

Nos últimos tempos, tenho sido preferindo as funções all e any, desde que eu raramente misture E e Ou comparações isso funciona bem, e tem a vantagem adicional de não precoce com geradores compreensão:

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

Apenas lembre-se de passar em um único iterable! Passando em N-argumentos não está correto.

Nota:. any é como muitas comparações or, all é como muitas comparações and


Isto combina muito bem com compreensões 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 em: gerador de compreensão

E se nós só inserir uma linha em branco adicionais entre o estado e o corpo e fazer o resto da forma canônica?

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

    do_something

P.S. Eu sempre uso guias, não espaços; Eu não posso afinar ...

Apenas algumas outras ideias aleatórias por amor de completude. Se eles trabalham para você, use-os. Caso contrário, você provavelmente é melhor tentar algo mais.

Você também pode fazer isso com um dicionário:

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

Esta opção é mais complicado, 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 eu não testei, mas os conceitos deve ser suficiente para você ir se é isso que você quer ir com ele.

(E para o registro, se esta é apenas uma coisa de uma vez, você provavelmente está apenas melhor fora de usar o método apresentado em primeiro lugar. Se você estiver fazendo a comparação em muitos lugares, esses métodos podem melhorar a legibilidade suficiente para fazer você se sentir tão mal sobre o fato de que eles são uma espécie de hacky.)

O que eu costumo fazer é:

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

Desta forma, a cinta de fecho e cólon marcar visualmente o fim da nossa condição.

Eu estive lutando para encontrar uma maneira decente para fazer isso bem, então eu só veio com uma idéia (não uma bala de prata, uma vez que esta é principalmente uma questão de gosto).

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

I encontrar alguns méritos desta solução em comparação com outros que vi, ou seja, você tem exatamente um extra de 4 espaços de recuo (bool), permitindo todas as condições para alinhar verticalmente, eo corpo da lata se declaração ser recuado de forma clara (ish). Isso também mantém os benefícios de curto-circuito avaliação 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 que retorna seu argumento poderia ser usado aqui em vez de bool, mas como eu disse, é apenas uma idéia e é em última análise, uma questão de gosto.

Engraçado o suficiente, como eu estava escrevendo este e pensar sobre o "problema", eu vim com outra idéia, que remove a sobrecarga de uma chamada de função. Por que não indica que estamos prestes a entrar em uma condição complexa usando pares extras de parênteses? Digamos, mais 2, para dar uma travessão espaço agradável 2 das sub-condições em relação ao corpo do 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 immediatelly na sua cabeça dizendo "hey, há uma coisa complexa acontecendo aqui!" . Sim, eu sei que os parênteses não ajuda a legibilidade, mas estas condições devem aparecer raramente suficiente, e quando o fazem aparecer, você vai ter que parar e lê-los carefuly qualquer maneira (porque eles são complexo ).

De qualquer forma, apenas mais duas propostas que eu não vi aqui. Espero que isso ajude alguém:)

Você pode dividi-lo em duas linhas

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

Ou até mesmo adicionar uma condição de cada vez. Dessa forma, pelo menos, ele separa a desordem do if.

Eu sei que esta discussão é antiga, mas eu tenho cerca de 2,7 código Python e PyCharm (4,5) ainda acusa sobre esse 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 visualmente recuado com o mesmo travessão na próxima linha lógica", o código real é completamente OK? Não é "over-recuar?"

... há momentos em que eu desejo Python teria pouco a bala e acabado com chaves. Pergunto-me quantos bugs foram introduzidas acidentalmente ao longo dos anos devido a acidentais mis-recuo ...

Todos os respondentes que também oferecem multi-condicionais para a instrução if é tão feio como o problema apresentado. Você não resolver este problema, fazendo a mesma coisa ..

Mesmo a resposta PEP 0008 é repulsivo.

Aqui é 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 comer minhas palavras? me convencer de que você precisa multi-condicionais e eu vou literalmente imprimir este e comê-lo para o seu divertimento.

Eu acho que @ solução de zkanda seria bom com uma pequena torção. Se você teve suas condições e valores em suas respectivas listas, você pode usar uma compreensão de lista para fazer a comparação, o que tornaria as coisas um pouco mais geral para a adição de 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 queria codificar uma declaração como esta, gostaria de escrever assim para legibilidade:

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

E só para jogar outra solução lá fora, com um operador iand :

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

if proceed:
    # do something

Arrumem as condições em uma lista, em seguida, fazer smth. como:

if False not in Conditions:
    do_something

Eu acho que quando eu tiver condições longos, muitas vezes eu tenho um corpo código curto. Nesse caso, eu apenas double-travessão do corpo, assim:

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

ou se esta é mais clara:

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

Não há nenhuma razão travessão deve ser um múltiplo de 4, neste caso, por exemplo, ver "Alinhado com delimitador de abertura":

http: //google-styleguide.googlecode. com / svn / trunk / pyguide.html? showone = Indentation # Indentation

Aqui está uma 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 torna mais fácil de adicionar outra condição facilmente sem alterar a declaração se simplesmente acrescentar outra condição à lista:

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

Eu costumo usar:

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

Se o nosso caso e uma condição mais tem para executar múltiplos dentro declaração dele do que podemos escrever como abaixo. Cada quando temos if else exemplo, com uma declaração dentro do mesmo.

Graças ele 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
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top