Question Est-ce que Python a un opérateur ternaire conditionnel?


Si Python n'a pas d'opérateur conditionnel ternaire, est-il possible de simuler un opérateur utilisant d'autres constructions de langage?


4427


origine


Réponses:


Oui c'était ajoutée dans la version 2.5.
La syntaxe est:

a if condition else b

Premier condition est évalué, alors soit a ou b est retourné en fonction de la Booléen valeur de condition
Si condition évalue à Vrai  a est retourné, sinon b est retourné.

Par exemple:

>>> 'true' if True else 'false'
'true'
>>> 'true' if False else 'false'
'false'

Notez que les conditions sont un expression, pas un déclaration. Cela signifie que vous ne pouvez pas utiliser d'affectations ou pass ou d'autres déclarations dans un conditionnel:

>>> pass if False else x = 3
  File "<stdin>", line 1
    pass if False else x = 3
          ^
SyntaxError: invalid syntax

Dans un tel cas, vous devez utiliser un if déclaration au lieu d'un conditionnel.


Gardez à l'esprit qu'il est désapprouvé par certains Pythonistas pour plusieurs raisons:

  • L'ordre des arguments est différent de beaucoup d'autres langages (tels que C, Ruby, Java, etc.), ce qui peut conduire à des bogues lorsque des gens non familiers du comportement "surprenant" de Python l'utilisent (ils peuvent inverser l'ordre).
  • Certains le trouvent "lourd", car il va à l'encontre du flux normal de la pensée (en pensant d'abord à la condition puis aux effets).
  • Raisons stylistiques.

Si vous avez du mal à vous souvenir de l'ordre, rappelez-vous que si vous le lisez à voix haute, vous (presque) dites ce que vous voulez dire. Par exemple, x = 4 if b > 8 else 9 est lu à voix haute x will be 4 if b is greater than 8 otherwise 9.

Documentation officielle


5285



Vous pouvez indexer dans un tuple:

(falseValue, trueValue)[test]

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

(falseValue, trueValue)[test == True]

ou vous pouvez utiliser le built-in bool() assurer une Booléen valeur:

(falseValue, trueValue)[bool(<expression>)]

591



Pour les versions antérieures à 2.5, voici l'astuce:

[expression] and [on_true] or [on_false]

Cela peut donner de mauvais résultats quand 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. Existe-t-il un équivalent de l'opérateur ternaire "?:" De C?


245



expression1 si condition autre expression2

>>> a = 1
>>> b = 2
>>> 1 if a > b else -1 
-1
>>> 1 if a > b else -1 if a < b else 0
-1

155



De La documentation:

Les expressions conditionnelles (parfois appelées un "opérateur ternaire") ont la priorité la plus basse 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; autrement, 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.


105



Un opérateur pour une expression conditionnelle en Python a été ajouté en 2006 dans le cadre de Proposition d'amélioration Python 308. Sa forme diffère de commune ?: opérateur et c'est:

<expression1> if <condition> else <expression2>

ce qui équivaut à:

if <condition>: <expression1> else: <expression2>

Voici un exemple:

result = x if a > b else y

Une autre syntaxe qui peut être utilisée (compatible avec les versions antérieures à 2.5):

result = (lambda:y, lambda:x)[a > b]()

où les opérandes sont évalué paresseusement.

Une autre méthode consiste à indexer un tuple (ce qui n'est pas cohérent avec l'opérateur conditionnel de la plupart des autres langages):

result = (y, x)[a > b]

ou dictionnaire explicitement construit:

result = {True: x, False: y}[a > b]

Une autre méthode (moins fiable) mais plus simple consiste à utiliser and et or les opérateurs:

result = (a > b) and x or y

cependant cela ne fonctionnera pas si x serait False.

Une solution possible est de faire x et y listes ou tuples comme suit:

result = ((a > b) and [x] or [y])[0]

ou:

result = ((a > b) and (x,) or (y,))[0]

Si vous travaillez avec des dictionnaires, au lieu d'utiliser un conditionnel ternaire, vous pouvez profiter de get(key, default), par exemple:

shell = os.environ.get('SHELL', "/bin/sh")

La source: ?: en Python sur Wikipedia


78



@up:

Malheureusement, le

(falseValue, trueValue)[test]

la solution n'a pas de comportement de court-circuit; donc falseValue et trueValue sont évalués quelle que soit la condition. Cela pourrait être sous-optimal ou même bogué (à la fois trueValue et falseValue pourraient être des méthodes et avoir des effets secondaires).

Une solution à cela serait

(lambda: falseValue, lambda: trueValue)[test]()

(exécution retardée jusqu'à ce que le gagnant soit connu;)), mais il introduit une incohérence entre les objets appelables et non-appelables. En outre, il ne résout pas le cas lors de l'utilisation des propriétés.

Et donc l'histoire va - choisir entre 3 solutions mentionnées est un compromis entre avoir la fonction de court-circuit, en utilisant au moins python 2.5 (IMHO n'est plus un problème) et ne pas être enclin à "trueValue-évalue-à-faux" les erreurs.


72



Pour Python 2.5 et plus récent, il existe une syntaxe spécifique:

[on_true] if [cond] else [on_false]

Dans les anciens Pythons, un opérateur ternaire n'est pas implémenté mais il est possible de le simuler.

cond and on_true or on_false

Cependant, il y a un problème potentiel, qui si cond évalue à True et on_true évalue à False puis on_false est retourné au lieu de on_true. Si vous voulez ce comportement, la méthode est OK, sinon utilisez ceci:

{True: on_true, False: on_false}[cond is True] # is True, not == True

qui peut être enveloppé par:

def q(cond, on_true, on_false)
    return {True: on_true, False: on_false}[cond is True]

et utilisé de cette façon:

q(cond, on_true, on_false)

Il est compatible avec toutes les versions de Python.


48