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



Answers

Vous pouvez indexer dans un tuple:

(falseValue, trueValue)[test]

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

(falseValue, trueValue)[test == True]

ou vous pouvez utiliser le Boolean intégré bool() pour assurer une valeur Boolean :

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

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




Plus une astuce qu'une réponse (pas besoin de répéter l'évidence pour la centième fois), mais je l'utilise parfois comme un raccourci oneliner dans de telles constructions:

if conditionX:
    print('yes')
else:
    print('nah')

, devient:

print('yes') if conditionX else print('nah')

Certains (beaucoup :) peuvent désapprouver comme non-pythonique (même, ruby-ish :), mais je trouve personnellement plus naturel - c'est-à-dire comment vous exprimer normalement, plus un peu plus attrayant visuellement dans de grands blocs de code.




Un opérateur pour une expression conditionnelle en Python a été ajouté en 2006 dans le cadre de Python Enhancement Proposal 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és 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 opérateurs:

result = (a > b) and x or y

cependant cela ne fonctionnera pas si x serait False .

Une solution de contournement possible consiste à créer des listes et des tuples x et y 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 utiliser get(key, default) , par exemple:

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

Source: ?:




In [1]: a = 1 if False else 0

In [2]: a
Out[2]: 0

In [3]: b = 1 if True else 0

In [4]: b
Out[4]: 1



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 la cond évaluée à True et on_true à False alors 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.




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

Oui. Du fichier de grammaire :

test: or_test ['if' or_test 'else' test] | lambdef

La partie d'intérêt est:

or_test ['if' or_test 'else' test]

Ainsi, une opération conditionnelle ternaire est de la forme:

expression1 if expression2 else expression3

expression3 sera évaluée paresseusement (c'est-à-dire, évaluée seulement si expression2 est fausse dans un contexte booléen). Et à cause de la définition récursive, vous pouvez les enchaîner indéfiniment (bien que cela puisse être considéré comme un mauvais style).

expression1 if expression2 else expression3 if expression4 else expression5 # and so on

Une note sur l'utilisation:

Notez que chaque if doit être suivi avec un else . Les personnes qui apprennent la compréhension des listes et les expressions génératrices peuvent trouver que c'est une leçon difficile à apprendre - ce qui suit ne fonctionnera pas, car Python attend une troisième expression pour un autre:

[expression1 if expression2 for element in iterable]
#                          ^-- need an else here

ce qui soulève une SyntaxError: invalid syntax . Donc, ce qui précède est soit une partie incomplète de la logique (peut-être l'utilisateur s'attend à un non-op dans la fausse condition) ou ce qui peut être destiné à utiliser expression2 comme un filtre - note que ce qui suit est légal Python:

[expression1 for element in iterable if expression2]

expression2 fonctionne comme un filtre pour la compréhension de la liste et n'est pas un opérateur conditionnel ternaire.

Syntaxe alternative pour un cas plus étroit:

Vous pourriez trouver quelque peu douloureux d'écrire ce qui suit:

expression1 if expression1 else expression2

expression1 devra être évaluée deux fois avec l'utilisation ci-dessus. Il peut limiter la redondance s'il s'agit simplement d'une variable locale. Cependant, un idiome Pythonic commun et performant pour ce cas d'utilisation est d'utiliser le comportement de raccourci:

expression1 or expression2

ce qui est équivalent en sémantique. Notez que certains guides de style peuvent limiter cette utilisation pour des raisons de clarté - cela ajoute beaucoup de sens à très peu de syntaxe.




expression1 si condition else expression2

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



Oui.

>>> b = (True if 5 > 4 else False)
>>> print b
True



Vous pourriez souvent trouver

cond and on_true or on_false

mais cela conduit à un problème lorsque on_true == 0

>>> x = 0
>>> print x == 0 and 0 or 1 
1
>>> x = 1
>>> print x == 0 and 0 or 1 
1

où vous attendez pour un opérateur ternaire normal ce résultat

>>> x = 0
>>> print 0 if x == 0 else 1 
0
>>> x = 1
>>> print 0 if x == 0 else 1 
1



Il y a une option ternaire comme indiqué dans les autres réponses, mais vous pouvez aussi la simuler en utilisant "ou" si vous comparez avec une valeur booléenne ou none:

>>> a = False
>>> b = 5
>>> a or b
5

>>> a = None
>>> a or b
5



Related