Si Python n'a pas d'opérateur conditionnel ternaire, est-il possible d'en simuler un en utilisant d'autres constructions de langage?
case [...] { when ... then ...} [ else ... ] end
un effet similaire mais pas du tout ternaire.
Si Python n'a pas d'opérateur conditionnel ternaire, est-il possible d'en simuler un en utilisant d'autres constructions de langage?
case [...] { when ... then ...} [ else ... ] end
un effet similaire mais pas du tout ternaire.
Réponses:
Oui, il a été ajouté dans la version 2.5. La syntaxe de l'expression est:
a if condition else b
Le premier condition
est évalué, puis exactement l'un des deux a
ou b
est évalué et renvoyé en fonction de la valeur booléenne de condition
. Si condition
évalue à True
, alors a
est évalué et renvoyé mais b
est ignoré, ou bien quand b
est évalué et renvoyé mais a
ignoré.
Cela permet de court-circuiter car quand condition
est vrai seulement a
est évalué et b
n'est pas évalué du tout, mais quand condition
est faux seulement b
est évalué et a
n'est pas évalué du tout.
Par exemple:
>>> 'true' if True else 'false'
'true'
>>> 'true' if False else 'false'
'false'
Notez que les conditions sont une expression , pas une instruction . Cela signifie que vous ne pouvez pas utiliser d'instructions d'affectation pass
ou 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
Vous pouvez cependant utiliser des expressions conditionnelles pour affecter une variable comme ceci:
x = a if True else b
Considérez l'expression conditionnelle comme une commutation entre deux valeurs. C'est très utile lorsque vous êtes dans une situation «une valeur ou une autre», mais cela ne fait pas grand-chose d'autre.
Si vous devez utiliser des instructions, vous devez utiliser une if
instruction normale au lieu d'une expression conditionnelle .
Gardez à l'esprit qu'il est mal vu par certains Pythonistes pour plusieurs raisons:
condition ? a : b
opérateur ternaire classique de nombreux autres langages (tels que C, C ++, Go, Perl, Ruby, Java, Javascript, etc.), ce qui peut conduire à des bugs lorsque les gens ne connaissent pas Python " un comportement "surprenant" l'utilise (ils peuvent inverser l'ordre des arguments).if
» puisse être vraiment utile et rendre votre script plus concis, il complique vraiment votre code)Si vous avez du mal à vous souvenir de la commande, n'oubliez pas que lorsque vous lisez à haute voix, vous dites (presque) ce que vous voulez dire. Par exemple, x = 4 if b > 8 else 9
est lu à haute voix comme x will be 4 if b is greater than 8 otherwise 9
.
Documentation officielle:
f(x) = |x| = x if x > 0 else -x
semble très naturel aux mathématiciens. Vous pouvez également le comprendre comme le fait A dans la plupart des cas, sauf lorsque C, alors vous devriez faire B à la place ...
z = 3 + x if x < y else y
. Si x=2
et y=1
, vous pourriez vous attendre à ce que cela donne 4, mais cela donnerait en fait 1. z = 3 + (x if x > y else y)
est l'utilisation correcte.
z = 3 + x if x < y else 3 + y
), soit regrouper le conditionnel ( z = 3 + (x if x < y else y)
ou z = (x if x < y else y) + 3
)
Vous pouvez indexer dans un tuple:
(falseValue, trueValue)[test]
test
doit renvoyer Vrai ou Faux .
Il pourrait être plus sûr de toujours l'implémenter comme:
(falseValue, trueValue)[test == True]
ou vous pouvez utiliser la fonction intégrée bool()
pour garantir une valeur booléenne :
(falseValue, trueValue)[bool(<expression>)]
(lambda: print("a"), lambda: print("b"))[test==true]()
[]
s peut être une expression arbitraire. En outre, pour des raisons de sécurité, vous pouvez explicitement tester la véracité en écrivant [bool(<expression>)]
. La bool()
fonction existe depuis la version 2.2.1.
True
et False
comme clés: {True:trueValue, False:falseValue}[test]
je ne sais pas si c'est moins efficace, mais cela évite au moins le tout débat "élégant" contre "laid". Il n'y a aucune ambiguïté que vous ayez affaire à un booléen plutôt qu'à un int.
Pour les versions antérieures à 2.5, voici l'astuce:
[expression] and [on_true] or [on_false]
Il peut donner des résultats erronés lorsqu'il on_true
a une fausse valeur booléenne. 1
Bien qu'il présente l'avantage d'évaluer les expressions de gauche à droite, ce qui est plus clair à mon avis.
<expression 1> if <condition> else <expression 2>
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
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 ( pas 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.
Un opérateur pour une expression conditionnelle en Python a été ajouté en 2006 dans le cadre de la proposition d'amélioration Python 308 . Sa forme diffère de celle de l' ?:
opérateur courant 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
Autre syntaxe utilisable (compatible avec les versions antérieures à 2.5):
result = (lambda:y, lambda:x)[a > b]()
où les opérandes sont paresseusement évalués .
Une autre façon consiste à indexer un tuple (ce qui n'est pas cohérent avec 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]
Un autre (moins fiable), mais plus simple méthode consiste à utiliser and
et les or
opérateurs:
result = (a > b) and x or y
mais cela ne fonctionnera pas si ce x
serait le cas False
.
Une solution possible est de faire x
et des 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 get(key, default)
, par exemple:
shell = os.environ.get('SHELL', "/bin/sh")
Source: ?: En Python sur Wikipedia
result = {1: x, 0: y}[a > b]
est une autre variante possible ( True
et False
sont en fait des entiers avec des valeurs 1
et 0
)
Malheureusement, le
(falseValue, trueValue)[test]
la solution n'a pas de comportement de court-circuit; ainsi les deux falseValue
et trueValue
sont évalués quelle que soit la condition. Cela pourrait être sous-optimal ou même bogué (c'est-à-dire les deux trueValue
et falseValue
pourrait être des méthodes et avoir des effets secondaires).
Une solution à ce problème 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. De plus, cela ne résout pas le cas lors de l'utilisation des propriétés.
Et donc l'histoire continue - choisir entre 3 solutions mentionnées est un compromis entre avoir la fonction de court-circuit, utiliser au moins Зython 2.5 (à mon humble avis plus un problème) et ne pas être sujet aux erreurs " trueValue
-évalue-à-faux" .
if else if
.
Ici, j'essaie juste de montrer une différence importante 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 à Ruby
a = true ? 1 : 0
# 1
b = false ? 1 : 0
# 0
Opérateur ternaire à 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
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 elle est cond
évaluée à True
et on_true
Equivaut à 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.
q("blob", on_true, on_false)
renvoie on_false
, tandis que on_true if cond else on_false
renvoie on_true
. Une solution de contournement consiste à remplacer cond
par cond is not None
dans ces cas, bien que ce ne soit pas une solution parfaite.
bool(cond)
place de cond is True
? Le premier vérifie la véracité de cond
, le second vérifie l'égalité du pointeur avec l' True
objet. Comme l'a souligné @AndrewCecil, "blob"
c'est vrai mais ça is not True
.
[on_false, on_True][cond is True]
pour que l'expression devienne plus courte.
Vous pourriez souvent trouver
cond and on_true or on_false
mais cela pose 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
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 évalué uniquement si expression2
est faux dans un contexte booléen). Et en raison de la définition récursive, vous pouvez les enchaîner indéfiniment (même si cela peut être considéré comme un mauvais style.)
expression1 if expression2 else expression3 if expression4 else expression5 # and so on
Notez que chaque if
doit être suivi d'un else
. Les personnes qui apprennent la compréhension de listes et les expressions de générateur peuvent trouver cela 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 un SyntaxError: invalid syntax
. Donc, ce qui précède est soit un morceau de logique incomplet (peut-être que l'utilisateur s'attend à un no-op dans la fausse condition) ou ce qui peut être prévu est d'utiliser expression2 comme filtre - note que ce qui suit est Python légal:
[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.
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. 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 or
le comportement de raccourci de:
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é - ils contiennent beaucoup de sens dans très peu de syntaxe.
expression1 or expression2
étant similaire et avec les mêmes inconvénients / positifs qu'en expression1 || expression2
javascript
expressionN
pour toutes les instances soit cohérente, il pourrait être plus facile à comprendre avec une dénomination qui distingue l'expression de test conditionnelle des deux expressions de résultat; par exemple result1 if condition else result2
. Cela est particulièrement évident lors de l' imbrication (aka enchaînant): result1 if condition1 else result2 if condition2 else result3
. Vous voyez à quel point cela se lit mieux?
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]()
production:
'b greater than a'
result = (y, x)[a < b]
Pourquoi utilisez-vous la lambda
fonction ?
L'opérateur conditionnel ternaire permet simplement de tester une condition sur une seule ligne en remplaçant le multiligne if-else rendant le code compact.
[on_true] if [expression] else [on_false]
# 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
# 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
# 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 s'écrire:
# 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
if-else
n'est pas réellement une réécriture de l'opérateur ternaire et produira une sortie différente pour les valeurs sélectionnées de a et b (en particulier si l'un est un type qui implémente une __ne__
méthode étrange ).
tu peux le faire :-
[condition] and [expression_1] or [expression_2] ;
Exemple:-
print(number%2 and "odd" or "even")
Cela afficherait "impair" si le nombre est impair ou "pair" si le nombre est pair.
Remarque :- 0, None, False, emptylist, emptyString est évalué comme False. Et toutes les données autres que 0 sont évaluées à True.
si la condition [condition] devient "True", alors expression_1 sera évaluée mais pas expression_2. Si nous "et" quelque chose avec 0 (zéro), le résultat sera toujours fasle. Donc dans l'instruction ci-dessous,
0 and exp
L'expression exp ne sera pas évaluée du tout car "et" avec 0 seront toujours évalués à zéro et il n'est pas nécessaire d'évaluer l'expression. C'est ainsi que le compilateur lui-même fonctionne, dans toutes les langues.
Dans
1 or exp
l'expression exp ne sera pas du tout évaluée car "ou" avec 1 sera toujours égal à 1. Il ne sera donc pas la peine d'évaluer l'expression exp puisque le résultat sera de toute façon 1. (méthodes d'optimisation du compilateur).
Mais en cas de
True and exp1 or exp2
La deuxième expression exp2 ne sera pas évaluée car True and exp1
serait True lorsque exp1 n'est pas fausse.
De même dans
False and exp1 or exp2
L'expression exp1 ne sera pas évaluée car False équivaut à écrire 0 et à faire "et" avec 0 serait 0 lui-même mais après exp1 puisque "ou" est utilisé, il évaluera l'expression exp2 après "ou".
Remarque: - Ce type de ramification utilisant "ou" et "et" ne peut être utilisé que lorsque l'expression_1 n'a pas la valeur Truth False (ou 0 ou None ou emptylist [] ou emptystring ''.) Car si expression_1 devient Faux, alors l'expression_2 sera évaluée en raison de la présence "ou" entre exp_1 et exp_2.
Dans le cas où vous souhaitez toujours le faire fonctionner pour tous les cas, quelles que soient les valeurs de vérité exp_1 et exp_2, procédez comme suit: -
[condition] and ([expression_1] or 1) or [expression_2] ;
x = [condition] and ([expression_1] or 1) or [expression_2]
et la expression_1
valeur false, x
sera 1
, non expression_1
. Utilisez la réponse acceptée.
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 raccourci oneliner 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-pythonique (même, ruby-ish :), mais je le trouve personnellement plus naturel - c'est-à-dire comment vous l'exprimeriez normalement, plus un peu plus visuellement attrayant dans de gros blocs de code.
print( 'yes' if conditionX else 'nah' )
ta réponse. :-)
print()
dans les deux cas - et ça a l'air un peu plus pythonique, je dois admettre :) Mais que se passe-t-il si les expressions / fonctions ne sont pas les mêmes - comme print('yes') if conditionX else True
- pour obtenir le print()
seul en véritéconditionX
print('yes') if conditionX else print('nah')
est qu'elle donne une SyntaxError en Python2.
print "yes"
, tandis que dans Python 3, c'est une fonction - print("yes")
. Cela peut être résolu soit en l'utilisant comme une déclaration, soit mieux - from future import print_function
.
L'une des alternatives à l' expression conditionnelle de Python
"yes" if boolean else "no"
est le suivant:
{True:"yes", False:"no"}[boolean]
qui a la belle extension suivante:
{True:"yes", False:"no", None:"maybe"}[boolean_or_none]
L'alternative la plus courte reste:
("no", "yes")[boolean]
mais il n'y a pas d'alternative à
yes() if boolean else no()
si vous voulez éviter l'évaluation de yes()
et no()
, parce que dans
(no(), yes())[boolean] # bad
les deux no()
et yes()
sont évalués.
De nombreux langages de programmation dérivés C
ont généralement la syntaxe d'opérateur conditionnel ternaire suivante:
<condition> ? <expression1> : <expression2>
Dans un premier temps , le
Python
B enevolent D ictator F ou L IFE (je veux dire Guido van Rossum, bien sûr) a rejeté (comme le style non Pythonic), car il est assez difficile à comprendre pour les gens non habitués à laC
langue. En outre, le signe deux-points:
a déjà de nombreuses utilisationsPython
. Après l' approbation du PEP 308 , il aPython
finalement reçu sa propre expression conditionnelle de raccourci (ce que nous utilisons maintenant):
<expression1> if <condition> else <expression2>
Donc, tout d'abord, il évalue la condition. S'il revient True
, expression1 sera évaluée pour donner le résultat, sinon expression2 sera évaluée. En raison de la mécanique d' évaluation paresseuse - 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 enchaî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.
Comme déjà répondu, oui il y a un opérateur ternaire en python:
<expression 1> if <condition> else <expression 2>
Information additionnelle:
Si tel<expression 1>
est le cas, vous pouvez utiliser l' évaluation à court terme :
a = True
b = False
# Instead of this:
x = a if a else b
# You could use Short-cirquit evaluation:
x = a or b
PS: Bien sûr, une évaluation de court-circuit n'est pas un opérateur ternaire mais souvent le ternaire est utilisé dans les cas où le court-circuit serait suffisant.
short-circuit
évaluation.
OUI, python a un opérateur ternaire, voici la syntaxe et un exemple de code pour le démontrer :)
#[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")
print
n'est vraiment pas un bon choix, car cela donnera une SyntaxError en Python2.
Python a une forme ternaire pour les affectations; cependant, il peut y avoir une forme encore plus courte que les gens devraient connaître.
Il est très courant de devoir attribuer à une variable une valeur ou une autre en fonction d'une condition.
>>> li1 = None
>>> li2 = [1, 2, 3]
>>>
>>> if li1:
... a = li1
... else:
... a = li2
...
>>> a
[1, 2, 3]
^ C'est la forme longue pour faire de telles tâches.
Voici la forme ternaire. Mais ce n'est pas la manière la plus succincte - voir le dernier exemple.
>>> a = li1 if li1 else li2
>>>
>>> a
[1, 2, 3]
>>>
Avec Python, vous pouvez simplement utiliser or
pour d'autres affectations.
>>> a = li1 or li2
>>>
>>> a
[1, 2, 3]
>>>
Ce qui précède fonctionne depuis li1
est None
et l'interp traite cela comme faux dans les expressions logiques. L'interp continue ensuite et évalue la deuxième expression, qui n'est pas None
et ce n'est pas une liste vide - elle est donc affectée à a.
Cela fonctionne également avec des listes vides. Par exemple, si vous souhaitez attribuer la a
liste contenant des éléments.
>>> li1 = []
>>> li2 = [1, 2, 3]
>>>
>>> a = li1 or li2
>>>
>>> a
[1, 2, 3]
>>>
Sachant cela, vous pouvez simplement de telles affectations chaque fois que vous les rencontrez. Cela fonctionne également avec les chaînes et autres itérables. Vous pouvez attribuer la a
chaîne qui n'est pas vide.
>>> s1 = ''
>>> s2 = 'hello world'
>>>
>>> a = s1 or s2
>>>
>>> a
'hello world'
>>>
J'ai toujours aimé la syntaxe C ternaire, mais Python va plus loin!
Je comprends que certains puissent dire que ce n'est pas un bon choix stylistique car il repose sur des mécanismes qui ne sont pas immédiatement apparents pour tous les développeurs. Personnellement, je ne suis pas d'accord avec ce point de vue. Python est un langage riche en syntaxe avec de nombreuses astuces idiomatiques qui ne sont pas immédiatement visibles pour le dabler. Mais plus vous apprenez et comprenez la mécanique du système sous-jacent, plus vous l'appréciez.
D'autres réponses parlent correctement de l'opérateur ternaire Python. Je voudrais compléter en mentionnant un scénario pour lequel l'opérateur ternaire est souvent utilisé mais pour lequel il existe un meilleur idiome. Il s'agit du scénario d'utilisation d'une valeur par défaut.
Supposons que nous voulons utiliser option_value
une valeur par défaut si elle n'est pas définie:
run_algorithm(option_value if option_value is not None else 10)
ou simplement
run_algorithm(option_value if option_value else 10)
Cependant, une meilleure solution consiste simplement à écrire
run_algorithm(option_value or 10)
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)
affichera
no Input
no Input
no Input
hello
['Hello']
True
x if x else y
, mais pas x if z else y
.
Une bonne façon 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
Je trouve lourde la syntaxe python par défaut val = a if cond else b
, donc parfois je fais ceci:
iif = lambda (cond, a, b): a if cond else b
# so I can then use it like:
val = iif(cond, a, b)
Bien sûr, il a l'inconvénient d'évaluer toujours les deux côtés (a et b), mais la syntaxe est beaucoup plus claire pour moi
val = a if cond else b
déclaration.
is_spacial=True if gender = "Female" else (True if age >= 65 else False)
**
il peut être imbriqué selon vos besoins. bonne chance
**