8004 votes

Est-ce que Python dispose d'un opérateur ternaire conditionnel ?

Y a-t-il un opérateur conditionnel ternaire en Python?

4 votes

Bien que les versions de Python antérieures à 2.5 s'éloignent lentement de l'histoire, voici une liste d'anciens astuces d'opérateur ternaire pré-2.5 : "Python Idioms", recherchez le texte 'Conditional expression' . Wikipedia est également très utile :-)

171 votes

Dans la documentation officielle de Python 3.0 mentionnée dans un commentaire ci-dessus, cela est appelé "expressions conditionnelles" et est défini de manière très cryptique. Cette documentation n'inclut même pas le terme "ternaire", donc vous auriez du mal à le trouver via Google à moins de savoir exactement ce que vous recherchez. La documentation de la version 2 est un peu plus utile et inclut un lien vers "PEP 308", qui comprend beaucoup de contexte historique intéressant lié à cette question.

35 votes

"ternaire" (ayant trois entrées) est une propriété conséquente de cette implémentation, et non une propriété définissante du concept. Ex : SQL a case [...] { when ... then ...} [ else ... ] end pour un effet similaire mais pas du tout ternaire.

9226voto

Vinko Vrsalovic Points 116138

Oui, il a été ajouté dans la version 2.5. La syntaxe de l'expression est :

a if condition else b

Tout d'abord, condition est évaluée, puis exactement l'un des éléments a ou b est évalué et retourné en fonction de la valeur booléenne de condition. Si condition est évaluée à True, alors a est évalué et retourné mais b est ignoré, sinon lorsque b est évalué et retourné mais a est ignoré.

Cela permet un court-circuit car lorsque condition est vraie, seul a est évalué et b n'est pas du tout évalué, mais lorsque condition est fausse, seul b est évalué et a n'est pas du tout évalué.

Par exemple :

>>> 'vrai' if True else 'faux'
'vrai'
>>> 'vrai' if False else 'faux'
'faux'

Remarque que les conditionnelles sont une expression, pas une déclaration. Cela signifie que vous ne pouvez pas utiliser de déclarations telles que pass, ou des affectations avec = (ou des affectations "augmentées" comme +=), à l'intérieur d'une expression conditionnelle :

>>> pass if False else pass
  File "", line 1
    pass if False else pass
         ^
SyntaxError: syntaxe invalide

>>> # Python analyse ceci comme `x = (1 if False else y) = 2`
>>> # La partie `(1 if False else x)` est en fait valide, mais
>>> # elle ne peut pas être du côté gauche de `=`.
>>> x = 1 if False else y = 2
  File "", line 1
SyntaxError: impossible d'assigner à une expression conditionnelle

>>> # Si nous parenthésageons à la place...
>>> (x = 1) if False else (y = 2)
  File "", line 1
    (x = 1) if False else (y = 2)
       ^
SyntaxError: syntaxe invalide

(À partir de la version 3.8, l'opérateur "morse" := permet l'affectation simple de valeurs comme une expression, ce qui est alors compatible avec cette syntaxe. Mais veuillez ne pas écrire un code de cette façon ; cela deviendra rapidement très difficile à comprendre.)

De même, étant donné qu'il s'agit d'une expression, la partie else est obligatoire :

# Syntaxe invalide : nous n'avons pas spécifié ce que la valeur devrait être si la
# condition n'est pas remplie. Peu importe si nous pouvons vérifier cela
# à l'avance.
a if True

Cependant, vous pouvez utiliser des expressions conditionnelles pour affecter une variable comme ceci :

x = a if True else b

Ou par exemple pour retourner une valeur :

# Bien sûr, nous devrions juste utiliser la bibliothèque standard `max`;
# ceci est juste à titre de démonstration.
def my_max(a, b):
    return a if a > b else b

Pensez à l'expression conditionnelle comme un commutateur entre deux valeurs. Nous pouvons l'utiliser lorsque nous sommes dans une situation de 'une valeur ou une autre', où nous allons faire la même chose avec le résultat, peu importe si la condition est remplie. Nous utilisons l'expression pour calculer la valeur, puis faisons quelque chose avec elle. Si vous avez besoin de faire quelque chose de différent en fonction de la condition, utilisez ensuite une if normale déclaration à la place.


Gardez à l'esprit que cela est mal vu par certains Pythonistes pour plusieurs raisons :

  • L'ordre des arguments est différent de celui de l'opérateur ternaire classique condition ? a : b de nombreux autres langages (comme C, C++, Go, Perl, Ruby, Java), JavaScript, etc.), ce qui peut entraîner des bugs lorsque des personnes peu familières avec le comportement "surprenant" de Python l'utilisent (elles peuvent inverser l'ordre des arguments).
  • Certains le trouvent "maladroit", car cela va à l'encontre du flux de pensée normal (penser d'abord à la condition puis aux effets).
  • Raisons stylistiques. (Bien que l' 'inline if' puisse être vraiment utile, et rendre votre script plus concis, cela complique vraiment votre code)

Si vous avez du mal à vous souvenir de l'ordre, alors souvenez-vous que lorsqu'on lit à voix haute, vous dites (presque) ce que vous voulez dire. Par exemple, x = 4 if b > 8 else 9 se lit à voix haute comme x sera 4 si b est supérieur à 8 sinon 9.

Documentation officielle :

363 votes

L'ordre peut sembler étrange pour les codeurs cependant f(x) = |x| = x if x > 0 else -x semble très naturel pour les mathématiciens. Vous pouvez aussi le comprendre comme faire A dans la plupart des cas, sauf quand C alors vous devriez faire B à la place...

177 votes

Faites attention à l'ordre des opérations lors de son utilisation. Par exemple, la ligne z = 3 + x if x < y else y. Si x=2 et y=1, vous pourriez vous attendre à obtenir 4, mais en réalité cela donnerait 1. z = 3 + (x if x > y else y) est l'utilisation correcte.

20 votes

Le point était que si vous voulez effectuer des évaluations supplémentaires après que la condition soit évaluée, comme ajouter une valeur au résultat, vous devrez soit ajouter l'expression supplémentaire des deux côtés (z = 3 + x if x < y else 3 + y), soit grouper la condition (z = 3 + (x if x < y else y) ou z = (x if x < y else y) + 3)

1014voto

landon9720 Points 11241

Vous pouvez indexer dans un tuple :

(falseValue, trueValue)[test]

test doit renvoyer Vrai ou Faux.
Il pourrait être plus sûr de l'implémenter toujours comme suit :

(falseValue, trueValue)[test == True]

ou vous pouvez utiliser la fonction intégrée bool() pour assurer une valeur Booléenne :

(falseValue, trueValue)[bool()]

735 votes

Notez que celui-ci évalue toujours tout, alors que la construction if/else n'évalue que l'expression gagnante.

146 votes

(lambda: print("a"), lambda: print("b"))[test==true]()

20 votes

Il convient de noter que ce qui se trouve entre les [] peut être une expression arbitraire. De plus, pour des raisons de sécurité, vous pouvez tester explicitement la vérité en écrivant [bool()]. La fonction bool() existe depuis la version 2.2.1.

442voto

James Brady Points 11646

Pour les versions antérieures à 2.5, il y a un truc:

[expression] and [on_true] or [on_false]

Cela peut donner des résultats incorrects lorsque on_true a une valeur booléenne fausse.1

Bien qu'il ait l'avantage d'évaluer les expressions de gauche à droite, ce qui est plus clair à mon avis.

1. <a href="http://docs.python.org/3.3/faq/programming.html#is-there-an-equivalent-of-c-s-ternary-operator" rel="noreferrer">Y a-t-il un équivalent de l'opérateur ternaire de C ”?:” ?</a>

79 votes

La solution consiste à utiliser (test and [true_value] or [false_value])[0], ce qui évite ce piège.

8 votes

L'opérateur ternaire s'exécute généralement plus rapidement (parfois de 10 à 25 %).

10 votes

@volcan Avez-vous une source pour moi?

365voto

Simon Zimmermann Points 1239

**if** **else**

a = 1
b = 2

1 if a > b else -1 
# Output is -1

1 if a > b else -1 if a < b else 0
# Output is -1

97 votes

Cela met en avant l'intention principale de l'opérateur ternaire : la sélection de valeur. Il montre également qu'il est possible de chaîner plusieurs opérateurs ternaires ensemble dans une seule expression.

7 votes

@Craig , je suis d'accord, mais il est également utile de savoir ce qui se passera lorsqu'il n'y a pas de parenthèses. Dans un vrai code, je tendrais aussi à insérer des parenthèses explicites.

1 votes

Utilisation : return 3 if t > 10 else t/2

210voto

Michael Burr Points 181287

De la documentation:

Les expressions conditionnelles (parfois appelées opérateur ternaire) ont la plus basse priorité de toutes les opérations Python.

L'expression x if C else y évalue d'abord la condition, C (pas x); si C est vrai, x est évalué et sa valeur est retournée; sinon, y est évalué et sa valeur est retournée.

Voir PEP 308 pour plus de détails sur les expressions conditionnelles.

Nouveau depuis la version 2.5.

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