web-dev-qa-db-fra.com

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

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

4966
Devoted

Oui, c'était ajouté dans la version 2.5. La syntaxe de l'expression est la suivante:

a if condition else b

La première variable condition est évaluée, puis l'une ou l'autre des variables a ou b est évaluée et renvoyée en fonction de la valeur Boolean de condition. Si condition est évalué à True, alors a est évalué et renvoyé, mais b est ignoré ou sinon, lorsque b est évalué et renvoyé mais a est ignoré.

Cela permet de court-circuiter car lorsque condition est vrai, seul a est évalué et b n'est pas du tout évalué, mais lorsque condition est faux, seul b est évalué et a n'est pas du tout évalué.

Par exemple:

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

Notez que les éléments conditionnels sont un expression, pas un instruction. Cela signifie que vous ne pouvez pas utiliser d'instructions d'affectation, ni pass ni d'autres instructions dans une expression conditionnelle:

>>> 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 ifstatement normal au lieu d'un expression conditionnel.


N'oubliez pas que certains pythonistes la désapprouvent pour plusieurs raisons:

  • L'ordre des arguments est différent de celui de l'opérateur ternaire condition ? a : b classique dans de nombreux autres langages (tels que C, C++, Go, Perl, Ruby, Java, Javascript, etc.), ce qui peut entraîner des erreurs lorsque les utilisateurs ne sont pas familiers avec Python. le comportement "surprenant" l'utilise (ils peuvent inverser l'ordre des arguments).
  • Certains le trouvent "lourd", car cela va à l’encontre du courant normal de la pensée (penser à la condition en premier lieu, puis aux effets).
  • Raisons stylistiques.

Si vous ne parvenez pas à vous rappeler l'ordre, souvenez-vous que, lorsqu'il est lu à haute voix, vous dites (presque) ce que vous voulez dire. Par exemple, x = 4 if b > 8 else 9 est lu à haute voix sous la forme x will be 4 if b is greater than 8 otherwise 9.

Documentation officielle: 

5921
Vinko Vrsalovic

Vous pouvez indexer dans un tuple:

(falseValue, trueValue)[test]

test doit renvoyer True ou False.
Il pourrait être plus sûr de toujours le mettre en œuvre de la manière suivante:

(falseValue, trueValue)[test == True]

ou vous pouvez utiliser la fonction bool() pour vous assurer que Boolean value:

(falseValue, trueValue)[bool(<expression>)]
657
Landon Kuhn

Pour les versions antérieures à la version 2.5, le truc est le suivant:

[expression] and [on_true] or [on_false]

Cela peut donner des résultats erronés lorsque on_true a une fausse valeur booléenne.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 C?

271
James Brady

expression1 if 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
175
Simon Zimmermann

De la documentation :

Les expressions conditionnelles (parfois appelées «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 (not x); si C est vrai, x est évalué et sa valeur est renvoyée; sinon, y est évalué et sa valeur est renvoyée.

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

Nouveau depuis la version 2.5.

122
Michael Burr

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

<expression1> if <condition> else <expression2>

qui équivaut à:

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

Voici un exemple:

result = x if a > b else y

Une autre syntaxe utilisable (compatible avec les versions antérieures à la 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 ne correspond pas à l'opérateur conditionnel de la plupart des autres langues):

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 les opérateurs and et or:

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 ou 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 utilisez des dictionnaires, au lieu d'utiliser un conditionnel ternaire, vous pouvez tirer parti de get(key, default) , par exemple:

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

Source: ?: En Python sur Wikipedia

92
kenorb

@up:

Malheureusement, le

(falseValue, trueValue)[test]

la solution n'a pas de comportement de court-circuit; ainsi, falseValue et trueValue sont évaluées indépendamment de la condition. Cela peut être sous-optimal ou même bogué (c’est-à-dire que trueValue et falseValue peuvent être des méthodes et avoir des effets secondaires).

Une solution à cela serait

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

(exécution différée jusqu'à ce que le gagnant soit connu;)), mais introduit une incohérence entre les objets appelables et non appelables. De plus, cela ne résout pas le problème lorsque vous utilisez des propriétés.

Et ainsi va l'histoire - le choix entre les 3 solutions mentionnées est un compromis entre avoir la fonctionnalité de court-circuit, utiliser au moins python 2.5 (IMHO n'est plus un problème) et ne pas être enclin à "trueValue-evaluates-to-false" les erreurs.

86
gorsky

Pour Python 2.5 et les versions plus récentes, il existe une syntaxe spécifique:

[on_true] if [cond] else [on_false]

Dans les Pythons plus anciens, 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 existe un problème potentiel qui, si cond est évalué à True et on_true est évalué à False, alors on_false est renvoyé au lieu de on_true. Si vous voulez que ce comportement la méthode soit OK, sinon utilisez ceci:

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

qui peut être emballé 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.

54
Paolo

Opérateur ternaire dans différents langages de programmation

Ici, je tente simplement de montrer une différence importante dans ternary operator entre quelques langages de programmation.

Opérateur ternaire en Javascript

var a = true ? 1 : 0;
# 1
var b = false ? 1 : 0;
# 0

Opérateur ternaire en rubis

a = true ? 1 : 0
# 1
b = false ? 1 : 0
# 0

Opérateur ternaire en Scala

val a = true ? 1 | 0
# 1
val b = false ? 1 | 0
# 0

Opérateur ternaire en programmation R

a <- if (TRUE) 1 else 0
# 1
b <- if (FALSE) 1 else 0
# 0

Opérateur ternaire en Python

a = 1 if True else 0
# 1
b = 1 if False else 0
# 0
51
Simplans

Vous pourriez souvent trouver

cond and on_true or on_false

mais cela pose problème quand 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 vous attendriez 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
35
Benoit Bertholon

Absolument, et c'est incroyablement facile à comprendre. 

general syntax : first_expression if bool_expression_is_true else second_expression

Example: x= 3 if 3 > 2 else 4 
# assigns 3 to x if the boolean expression evaluates to true or 4 if it is false
30
BattleDrum

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

Oui. À partir 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é paresseusement (c’est-à-dire qu’il n’est évalué que si expression2 est faux dans un contexte booléen). Et à cause de la définition récursive, vous pouvez les chaî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 d'un else. Les personnes apprenant la compréhension des listes et les expressions génératrices peuvent trouver cette leçon difficile à apprendre. Ce qui suit ne fonctionnera pas, car Python attend une troisième expression pour une autre:

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

ce qui soulève un SyntaxError: invalid syntax. Donc, ce qui précède est soit un élément de logique incomplet (peut-être que l'utilisateur s'attend à un non-fonctionnement dans la condition fausse) ou bien ce que l'on peut vouloir utiliser est d'utiliser l'expression2 comme filtre. Python légal:

[expression1 for element in iterable if expression2]

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

Syntaxe alternative pour un cas plus étroit:

Vous trouverez peut-être un peu pénible d’écrire ce qui suit:

expression1 if expression1 else expression2

expression1 devra être évalué deux fois avec l'utilisation ci-dessus. Cela 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 consiste à utiliser le comportement de raccourci de or:

expression1 or expression2

ce qui est équivalent en sémantique. Notez que certains guides de style peuvent limiter cet usage pour des raisons de clarté - il contient beaucoup de signification dans très peu de syntaxe.

27
Aaron Hall

Simulation de l'opérateur ternaire python.

Par exemple

a, b, x, y = 1, 2, 'a greather than b', 'b greater than a'
result = (lambda:y, lambda:x)[a > b]()

sortie:

'b greater than a'
17
Sasikiran Vaddi

L'opérateur conditionnel ternaire permet simplement de tester une condition sur une seule ligne, en remplaçant le multiligne si ce qui rend le code compact.

Syntaxe:

[on_true] if [expression] else [on_false] 

1- Méthode simple d'utilisation de l'opérateur ternaire:

# Program to demonstrate conditional operator
a, b = 10, 20
# Copy value of a in min if a < b else copy b
min = a if a < b else b
print(min)  # Output: 10

2- Méthode directe d’utilisation de tuples, Dictionary et lambda:

# Python program to demonstrate ternary operator
a, b = 10, 20
# Use Tuple for selecting an item
print( (b, a) [a < b] )
# Use Dictionary for selecting an item
print({True: a, False: b} [a < b])
# lamda is more efficient than above two methods
# because in lambda  we are assure that
# only one expression will be evaluated unlike in
# Tuple and Dictionary
print((lambda: b, lambda: a)[a < b]()) # in output you should see three 10

3- L'opérateur ternaire peut être écrit imbriqué si-else:

# Python program to demonstrate nested ternary operator
a, b = 10, 20
print ("Both a and b are equal" if a == b else "a is greater than b"
        if a > b else "b is greater than a")

L'approche ci-dessus peut être écrite comme suit:

# Python program to demonstrate nested ternary operator
a, b = 10, 20
if a != b:
    if a > b:
        print("a is greater than b")
    else:
        print("b is greater than a")
else:
    print("Both a and b are equal") 
# Output: b is greater than a
14
Ali Hallaji

Plus un conseil qu'une réponse (vous n'avez pas besoin de répéter l'évidence pour la centaine de fois), mais je l'utilise parfois comme raccourci rapide dans de telles constructions:

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

, devient:

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

Certains (beaucoup :) peuvent le considérer comme non rythmique (même Ruby-ish :), mais personnellement, je trouve cela plus naturel - c’est-à-dire comment vous l’exprimeriez normalement, plus un peu plus attrayant visuellement dans de gros blocs de code.

12
Todor Minakov

Oui, vous pouvez l'utiliser de cette façon: 

is_fat = True
state = "fat" if is_fat else "not fat"

En savoir plus sur opérateur conditionnel ternaire

10
Daniel Taub
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
10
ox.
a if condition else b

Mémorisez cette pyramide si vous avez du mal à vous souvenir:

     condition
  if           else
a                   b 
7
shivtej

OUI, python a un opérateur ternaire, voici la syntaxe et un exemple de code pour démontrer la même chose :)

#[On true] if [expression] else[On false]
# if the expression evaluates to true then it will pass On true otherwise On false


a= input("Enter the First Number ")
b= input("Enter the Second Number ")

print("A is Bigger") if a>b else print("B is Bigger")
6
PythonLover

Syntaxe: L'opérateur ternaire sera donné par:

[on_true] if [expression] else [on_false]

par exemple

x, y = 25, 50
big = x if x < y else y
print(big)
4

Oui.

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

De nombreux langages de programmation dérivés de C ont généralement la syntaxe suivante pour l'opérateur conditionnel ternaire:

<condition> ? <expression1> : <expression2>

Au début, la PythonB enevolent D ictateur F ou L ife (je veux dire Guido van Rossum, bien sûr ) l'a rejeté (comme dans un style non Pythonic), car il est assez difficile à comprendre pour les personnes non habituées au langage C. De plus, le signe deux-points : a déjà de nombreuses utilisations dans Python. Après l'approbation de PEP 308, Python a finalement reçu sa propre expression conditionnelle de raccourci (ce que nous utilisons maintenant):

<expression1> if <condition> else <expression2>

Donc, premièrement, il évalue la condition. S'il renvoie True, expression1 sera évalué pour donner le résultat, sinon expression2 sera évalué. En raison de la mécanique Lazy Evaluation _, une seule expression sera exécutée.

Voici quelques exemples (les conditions seront évaluées de gauche à droite):

pressure = 10
print('High' if pressure < 20 else 'Critical')

# Result is 'High'

Les opérateurs ternaires peuvent être chaînés en série: 

pressure = 5
print('Normal' if pressure < 10 else 'High' if pressure < 20 else 'Critical')

# Result is 'Normal'

Le suivant est le même que le précédent:

pressure = 5

if pressure < 20:
    if pressure < 10:
        print('Normal')
    else:
        print('High')
else:
    print('Critical')

# Result is 'Normal'

J'espère que cela t'aides.

3
ARGeo

L'opérateur est "conditionnel". Ternary signifie simplement qu'il faut trois opérandes. Nous n'appelons pas + l'opérateur "binaire" +. Il n'y a aucune raison de continuer à le faire avec conditionnel. Que ce soit plus rapide ou plus compact que si-sinon est à côté du point. Ce qui compte, c’est que c’est une expression qui permet de l’intégrer à d’autres expressions. Correctement utilisé, il réduit la redondance et les opportunités de différences difficiles à identifier.

1
David McCracken

Une des alternatives à l'expression conditionnelle de Python est la suivante:

{True:"yes", False:"no"}[boolean]

qui a l'extension de Nice suivante:

{True:"yes", False:"no", None:"maybe"}[boolean_or_none]

La plus courte alternative reste:

("no", "yes")[boolean]

mais il n'y a pas d'alternative si vous voulez éviter l'évaluation de yes() et de no() dans ce qui suit:

yes() if [condition] else no()
1
Walter Tross

Oui:

Supposons que vous vouliez donner à la variable x une valeur si un booléen est vrai et que 

X = 5 si autre chose x = 10

X = [une valeur] if [si ceci est vrai, la première valeur est évaluée] else [une autre valeur est évaluée]

1
Elad Goldenberg

si la variable est définie et que vous voulez vérifier si elle a une valeur, vous pouvez simplement a or b

def test(myvar=None):
    # shorter than: print myvar if myvar else "no Input"
    print myvar or "no Input"

test()
test([])
test(False)
test('hello')
test(['Hello'])
test(True)

va sortir

no Input
no Input
no Input
hello
['Hello']
True
0
ewwink

Un moyen astucieux de chaîner plusieurs opérateurs:

f = lambda x,y: 'greater' if x > y else 'less' if y > x else 'equal'

array = [(0,0),(0,1),(1,0),(1,1)]

for a in array:
  x, y = a[0], a[1]
  print(f(x,y))

# Output is:
#   equal,
#   less,
#   greater,
#   equal

0
Yaakov Bressler