Si Python n'a pas d'opérateur conditionnel ternaire, est-il possible d'en simuler un en utilisant d'autres constructions de langage?
6050
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:
Le premier
condition
est évalué, puis exactement l'un des deuxa
oub
est évalué et renvoyé en fonction de la valeur booléenne decondition
. Sicondition
évalue àTrue
, alorsa
est évalué et renvoyé maisb
est ignoré, ou bien quandb
est évalué et renvoyé maisa
ignoré.Cela permet de court-circuiter car quand
condition
est vrai seulementa
est évalué etb
n'est pas évalué du tout, mais quandcondition
est faux seulementb
est évalué eta
n'est pas évalué du tout.Par exemple:
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 :Vous pouvez cependant utiliser des expressions conditionnelles pour affecter une variable comme ceci:
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 commex will be 4 if b is greater than 8 otherwise 9
.Documentation officielle:
la source
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
. Six=2
ety=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)
ouz = (x if x < y else y) + 3
)Vous pouvez indexer dans un tuple:
test
doit renvoyer Vrai ou Faux .Il pourrait être plus sûr de toujours l'implémenter comme:
ou vous pouvez utiliser la fonction intégrée
bool()
pour garantir une valeur booléenne :la source
(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>)]
. Labool()
fonction existe depuis la version 2.2.1.True
etFalse
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:
Il peut donner des résultats erronés lorsqu'il
on_true
a une fausse valeur booléenne. 1Bien qu'il présente l'avantage d'évaluer les expressions de gauche à droite, ce qui est plus clair à mon avis.
1. Y a-t-il un équivalent d'opérateur ternaire C? »:«?
la source
<expression 1> if <condition> else <expression 2>
la source
De la documentation :
Nouveau depuis la version 2.5.
la source
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:ce qui équivaut à:
Voici un exemple:
Autre syntaxe utilisable (compatible avec les versions antérieures à 2.5):
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):
ou dictionnaire explicitement construit:
Un autre (moins fiable), mais plus simple méthode consiste à utiliser
and
et lesor
opérateurs:mais cela ne fonctionnera pas si ce
x
serait le casFalse
.Une solution possible est de faire
x
et desy
listes ou tuples comme suit:ou:
Si vous travaillez avec des dictionnaires, au lieu d'utiliser un conditionnel ternaire, vous pouvez profiter
get(key, default)
, par exemple:Source: ?: En Python sur Wikipedia
la source
result = {1: x, 0: y}[a > b]
est une autre variante possible (True
etFalse
sont en fait des entiers avec des valeurs1
et0
)Malheureusement, le
la solution n'a pas de comportement de court-circuit; ainsi les deux
falseValue
ettrueValue
sont évalués quelle que soit la condition. Cela pourrait être sous-optimal ou même bogué (c'est-à-dire les deuxtrueValue
etfalseValue
pourrait être des méthodes et avoir des effets secondaires).Une solution à ce problème serait
(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" .la source
if else if
.Opérateur ternaire dans différents langages de programmation
Ici, j'essaie juste de montrer une différence importante
ternary operator
entre quelques langages de programmation.la source
Pour Python 2.5 et plus récent, il existe une syntaxe spécifique:
Dans les anciens Pythons, un opérateur ternaire n'est pas implémenté mais il est possible de le simuler.
Cependant, il y a un problème potentiel qui , si elle est
cond
évaluée àTrue
eton_true
Equivaut àFalse
puison_false
est retourné au lieu deon_true
. Si vous voulez ce comportement, la méthode est OK, sinon utilisez ceci:qui peut être enveloppé par:
et utilisé de cette façon:
Il est compatible avec toutes les versions de Python.
la source
q("blob", on_true, on_false)
renvoieon_false
, tandis queon_true if cond else on_false
renvoieon_true
. Une solution de contournement consiste à remplacercond
parcond is not None
dans ces cas, bien que ce ne soit pas une solution parfaite.bool(cond)
place decond is True
? Le premier vérifie la véracité decond
, le second vérifie l'égalité du pointeur avec l'True
objet. Comme l'a souligné @AndrewCecil,"blob"
c'est vrai mais çais not True
.[on_false, on_True][cond is True]
pour que l'expression devienne plus courte.Vous pourriez souvent trouver
mais cela pose problème lorsque on_true == 0
où vous attendez pour un opérateur ternaire normal ce résultat
la source
Oui. À partir du fichier de grammaire :
La partie d'intérêt est:
Ainsi, une opération conditionnelle ternaire est de la forme:
expression3
sera évalué paresseusement (c'est-à-dire évalué uniquement siexpression2
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.)Une note sur l'utilisation:
Notez que chaque
if
doit être suivi d'unelse
. 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: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: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 trouverez peut-être un peu pénible d'écrire ce qui suit:
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'utiliseror
le comportement de raccourci de: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.
la source
expression1 or expression2
étant similaire et avec les mêmes inconvénients / positifs qu'enexpression1 || expression2
javascriptexpressionN
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 exempleresult1 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
production:
la source
result = (y, x)[a < b]
Pourquoi utilisez-vous lalambda
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.
Syntaxe:
1- Méthode simple pour utiliser l'opérateur ternaire:
2- Méthode directe d'utilisation des tuples, du dictionnaire et du lambda:
3- L'opérateur ternaire peut s'écrire comme imbriqué if-else:
L'approche ci-dessus peut s'écrire:
la source
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.
Le résultat :- Si la condition est vraie, exp_1 est exécutée, sinon exp_2 est exécutée.
Remarque :- 0, None, False, emptylist, emptyString est évalué comme False. Et toutes les données autres que 0 sont évaluées à True.
Voici comment ça fonctionne:
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,
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
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
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
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] ;
la source
x = [condition] and ([expression_1] or 1) or [expression_2]
et laexpression_1
valeur false,x
sera1
, nonexpression_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:
, devient:
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.
la source
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 - commeprint('yes') if conditionX else True
- pour obtenir leprint()
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
.Mémorisez simplement cette pyramide si vous avez du mal à vous souvenir:
la source
L'une des alternatives à l' expression conditionnelle de Python
est le suivant:
qui a la belle extension suivante:
L'alternative la plus courte reste:
mais il n'y a pas d'alternative à
si vous voulez éviter l'évaluation de
yes()
etno()
, parce que dansles deux
no()
etyes()
sont évalués.la source
De nombreux langages de programmation dérivés
C
ont généralement la syntaxe d'opérateur conditionnel ternaire suivante: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):
Les opérateurs ternaires peuvent être enchaînés en série:
Le suivant est le même que le précédent:
J'espère que cela t'aides.
la source
Comme déjà répondu, oui il y a un opérateur ternaire en python:
Information additionnelle:
Si tel
<expression 1>
est le cas, vous pouvez utiliser l' évaluation à court terme :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.
la source
short-circuit
évaluation.OUI, python a un opérateur ternaire, voici la syntaxe et un exemple de code pour le démontrer :)
la source
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.
^ 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.
Avec Python, vous pouvez simplement utiliser
or
pour d'autres affectations.Ce qui précède fonctionne depuis
li1
estNone
et l'interp traite cela comme faux dans les expressions logiques. L'interp continue ensuite et évalue la deuxième expression, qui n'est pasNone
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.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.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.
la source
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:ou simplement
Cependant, une meilleure solution consiste simplement à écrire
la source
si la variable est définie et que vous voulez vérifier si elle a une valeur, vous pouvez simplement
a or b
affichera
la source
x if x else y
, mais pasx if z else y
.Une bonne façon de chaîner plusieurs opérateurs:
la source
Je trouve lourde la syntaxe python par défaut
val = a if cond else b
, donc parfois je fais ceci: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
la source
val = a if cond else b
déclaration.**
**
la source