Question Styler les conditions multilignes dans les instructions 'if'?


Parfois, je casse de longues conditions dans ifs sur plusieurs lignes. La manière la plus évidente de faire ceci est:

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

N'est pas très attrayant visuellement, car l'action se confond avec les conditions. Cependant, c'est la façon naturelle d'utiliser l'indentation Python correcte de 4 espaces.

Pour le moment j'utilise:

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

Mais ce n'est pas très joli. :-)

Pouvez-vous recommander une alternative?


469
2017-10-08 06:19


origine


Réponses:


Vous n'avez pas besoin d'utiliser 4 espaces sur votre deuxième ligne conditionnelle. Peut-être utiliser:

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

De plus, n'oubliez pas que les espaces blancs sont plus flexibles que vous ne le pensez:

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

Les deux sont assez moche cependant.

Peut-être perdre les parenthèses (le Guide de style décourage cela cependant)?

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

Cela vous donne au moins une certaine différenciation.

Ou même:

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

Je pense que je préfère:

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

Ici se trouve le Guide de style, qui (depuis 2010) recommande d'utiliser des crochets.


502
2017-10-08 06:34



J'ai eu recours à ce qui suit dans le cas dégénéré où ce sont simplement des AND ou des OR.

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

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

Il rase quelques personnages et indique clairement qu’il n’ya pas de subtilité dans la condition.


93
2017-10-08 10:26



Quelqu'un doit défendre l'utilisation des espaces verticaux ici! :)

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

Cela rend chaque condition clairement visible. Il permet également l'expression plus propre de conditions plus complexes:

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

Oui, nous échangeons un peu de l'immobilier vertical pour plus de clarté. Ça valait vraiment la peine.


45
2017-10-08 14:55



Je suggère de déplacer le and mot-clé à la deuxième ligne et indentant toutes les lignes contenant des conditions avec deux espaces au lieu de quatre:

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

C'est exactement comme ça que je résous ce problème dans mon code. Avoir un mot-clé comme premier mot de la ligne rend la condition beaucoup plus lisible et réduire le nombre d’espaces permet de mieux distinguer la condition de l’action.


19
2017-10-08 07:19



Cela ne s'améliore pas tellement mais ...

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

if allCondsAreOK:
   do_something

17
2017-10-08 06:31



Voici ma prise très personnelle: les longues conditions sont (à mon avis) une odeur de code qui suggère un refactoring en une fonction / méthode de retour booléen. Par exemple:

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

Maintenant, si je trouvais un moyen de faire bien paraître les conditions multi-lignes, je me trouverais probablement content de les avoir et de sauter le refactoring.

D'un autre côté, les avoir perturbés mon sens esthétique incite à la refactorisation.

Ma conclusion est donc que les conditions sur plusieurs lignes doivent paraître laides, ce qui incite à les éviter.


17
2018-01-14 10:50



Je préfère ce style quand j'ai une si-condition terriblement grande:

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

15
2017-10-08 08:39



Il semble intéressant de citer PEP 0008 (Guide de style officiel de Python), car il commente cette question à une longueur modeste:

Lorsque la partie conditionnelle d'un if -statement est assez long pour exiger qu'il soit écrit sur plusieurs lignes, il convient de noter que la combinaison d'un mot-clé à deux caractères (c'est-à-dire if ), plus un seul espace, plus une parenthèse d’ouverture crée un retrait naturel de 4 espaces pour les lignes suivantes du conditionnel multiligne. Cela peut produire un conflit visuel avec la suite indentée de code imbriquée dans le if-statement, qui serait aussi naturellement indenté à 4 espaces. Ce PEP ne prend pas de position explicite sur la façon (ou non) de distinguer visuellement de telles lignes conditionnelles de la suite imbriquée à l'intérieur du if -déclaration. Les options acceptables dans cette situation incluent, mais ne sont pas limitées à:

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

Notez le "pas limité à" dans la citation ci-dessus; Outre les approches suggérées dans le guide de style, certaines des solutions proposées dans d'autres réponses à cette question sont également acceptables.


9
2017-07-05 14:15



Voici ce que je fais, rappelez-vous que "tout" et "tout" accepte un itérable, donc je mets juste une longue condition dans une liste et laisse "tout" faire le travail.

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

if all(condition):
   do_something

5
2017-11-19 03:34



Je suis surpris de ne pas voir ma solution préférée,

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

Depuis and est un mot-clé, il est mis en évidence par mon éditeur et est suffisamment différent du do_something situé en dessous.


4
2018-01-14 14:50