28 votes

Affectation élégante de Python basée sur des valeurs Vrai / Faux

J'ai une variable que je veux régler selon les valeurs de trois booléens. La plus straight-forward est un si la déclaration suivie par une série de elifs:

if a and b and c:
    name = 'first'
elif a and b and not c:
    name = 'second'
elif a and not b and c:
    name = 'third'
elif a and not b and not c:
    name = 'fourth'
elif not a and b and c:
    name = 'fifth'
elif not a and b and not c:
    name = 'sixth'
elif not a and not b and c:
    name = 'seventh'
elif not a and not b and not c:
    name = 'eighth'

C'est un peu maladroit, et je me demandais si il n'y a plus Pythonic façon de traiter ce problème. Quelques idées me viennent à l'esprit.

  1. Dictionnaire hack:

    name = {a and b and c: 'first',
            a and b and not c: 'second',
            a and not b and c: 'third',
            a and not b and not c: 'fourth',
            not a and b and c: 'fifth',
            not a and b and not c: 'sixth',
            not a and not b and c: 'seventh',
            not a and not b and not c: 'eighth'}[True]
    

J'appelle cela un hack parce que je ne suis pas trop sauvage sur sept des clés à Faux et en remplaçant les uns les autres.

  1. Et/ou de la magie

    name = (a and b and c and 'first' or
            a and b and not c and 'second' or
            a and not b and c and 'third' or
            a and not b and not c and 'fourth' or
            not a and b and c and 'fifth' or
            not a and b and not c and 'sixth' or
            not a and not b and c and 'seventh' or
            not a and not b and not c and 'eighth')
    

Cela fonctionne parce que Python ands et rup retourne la dernière valeur qui doit être évalué, mais vous devez savoir que pour comprendre ce bizarre code.

Aucune de ces trois options est très satisfaisant. Que recommandez-vous?

50voto

Clint Miller Points 6339

Vous pouvez considérer a, b et c comme trois bits qui, lorsqu'ils sont assemblés, forment un nombre compris entre 0 et 7. Ensuite, vous pouvez avoir un tableau de valeurs ['premier', 'deuxième', ... 'huitième' ] et utilisez la valeur de bit comme décalage dans le tableau. Ce ne serait que deux lignes de code (une pour assembler les bits en une valeur de 0 à 7, et une pour rechercher la valeur dans le tableau).

Voici le code:

 nth = ['eighth', 'seventh', 'sixth', 'fifth', 'fourth', 'third', 'second', 'first']
nth[(a and 4 or 0) | (b and 2 or 0) | (c and 1 or 0)]
 

29voto

Tim Pietzcker Points 146308

Que diriez-vous d'utiliser un dict?

 name = {(True, True, True): "first", (True, True, False): "second",
        (True, False, True): "third", (True, False, False): "fourth",
        (False, True, True): "fifth", (False, True, False): "sixth",
        (False, False, True): "seventh", (False, False, False): "eighth"}

print name[a,b,c] # prints "fifth" if a==False, b==True, c==True etc.
 

11voto

Sven Marnach Points 133943

Peut-être pas beaucoup mieux, mais que diriez-vous

 results = ['first', 'second', 'third', 'fourth', 
           'fifth', 'sixth', 'seventh', 'eighth']
name = results[((not a) << 2) + ((not b) << 1) + (not c)]
 

5voto

eyquem Points 9942

si a, b, c sont vraiment des booléens:

 li = ['eighth', 'seventh', 'sixth', 'fifth', 'fourth', 'third', 'second', 'first']
name = li[a*4 + b*2 + c]
 

si ce ne sont pas des booléens:

 li = ['eighth', 'seventh', 'sixth', 'fifth', 'fourth', 'third', 'second', 'first']
a,b,c = map(bool,(a,b,c))
name = li[a*4 + b*2 + c]
 

idée de Clint Miller

2voto

OscarRyz Points 82553

Depuis que vous obtenez toutes les combinaisons, vous pouvez créer un index basé sur les valeurs comme ceci:

 def value(a,b,c ): 
   values = ['8th','7th','6th','5th','4th','3rd','2nd','1st']
   index = ( 4 if a else 0 ) + ( 2 if b else 0 ) + ( 1 if c else 0 )
   return values[index]

if __name__ == "__main__":
   print value(True,  True,  True )
   print value(True,  True,  False )
   print value(True,  False, True )
   print value(True,  False, False )
   print value(False, True,  True )
   print value(False, True,  False)
   print value(False, False, True )
   print value(False, False, False)
 

production:

 1st
2nd
3rd
4th
5th
6th
7th
8th
 

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X