J'ai un script python qui peut recevoir zéro ou trois arguments de ligne de commande. (Soit il s'exécute sur le comportement par défaut, soit il a besoin des trois valeurs spécifiées.)
Quelle est la syntaxe idéale pour quelque chose comme:
if a and (not b or not c) or b and (not a or not c) or c and (not b or not a):
?
python
if-statement
Chris Wilson
la source
la source
len(sys.argv)
sera toujours au moins égal à 1: il inclut l'exécutable sous la formeargv[0]
.if not (a and b and c)
(zéro argument), puisif a and b and c
(les trois arguments)?Réponses:
Si vous voulez dire une forme minimale, allez-y:
Ce qui traduit le titre de votre question.
MISE À JOUR: comme correctement dit par Volatility et Supr, vous pouvez appliquer la loi de De Morgan et obtenir l'équivalent:
Mon conseil est d'utiliser la forme la plus importante pour vous et pour les autres programmeurs. Le premier signifie "il y a quelque chose de faux, mais aussi quelque chose de vrai" , le second "il y a quelque chose de vrai, mais pas tout" . Si je devais optimiser ou faire cela dans le matériel, je choisirais le second, ici il suffit de choisir le plus lisible (en tenant également compte des conditions que vous allez tester et de leurs noms). J'ai choisi le premier.
la source
if not (a and b and c) and (a or b or c)
if (a or b or c) and not (a and b and c)
pour correspondre parfaitement au titre;)if any([a,b,c]) and not all([a,b,c])
Que diriez-vous:
Autre variante:
la source
sum(conditions)
peut mal tourner si l'un d'eux revient2
par exemple, ce qui estTrue
.sum(map(bool, conditions))
Cette question avait déjà de nombreuses réponses très positives et une réponse acceptée, mais jusqu'à présent, toutes étaient distraites par diverses façons d'exprimer le problème booléen et ont manqué un point crucial:
Cette logique ne doit pas être la responsabilité de votre code en premier lieu , elle doit plutôt être gérée par
argparse
module. Ne vous embêtez pas à écrire une instruction if complexe, préférez plutôt configurer votre analyseur d'arguments comme ceci:Et oui, cela devrait être une option et non un argument positionnel, car après tout, il est facultatif .
édité: Pour répondre à la préoccupation de LarsH dans les commentaires, voici un exemple de la façon dont vous pourriez l'écrire si vous étiez certain de vouloir l'interface avec 3 ou 0arguments positionnels . Je suis d'avis que l'interface précédente est un meilleur style, car les arguments optionnels devraient être des options , mais voici une approche alternative par souci d'exhaustivité. Notez le kwarg de remplacement
usage
lors de la création de votre analyseur, carargparse
sinon, cela générera automatiquement un message d'utilisation trompeur!Voici quelques exemples d'utilisation:
la source
J'irais pour:
Je pense que cela devrait court-circuiter assez efficacement
Explication
En créant
conds
un itérateur, la première utilisation deany
court-circuitera et laissera l'itérateur pointant vers l'élément suivant si un élément est vrai; sinon, il consommera la liste entière et seraFalse
. Le suivantany
prend les éléments restants dans l'itérable, et s'assure qu'il n'y a pas d'autres valeurs vraies ... S'il y en a, la déclaration entière ne peut pas être vraie, donc il n'y a pas un élément unique (donc des courts-circuits encore). Le dernierany
retourneraFalse
ou épuisera l'itérable et seraTrue
.Remarque: les contrôles ci-dessus vérifient si une seule condition est définie
Si vous souhaitez vérifier si un ou plusieurs éléments, mais pas tous, sont définis, vous pouvez utiliser:
la source
[a, b, c] = [True, True, False]
votre code ne devrait-il pas "s'imprimer"False
, alors que la sortie attendue estTrue
?iter
.any
etall
consommera paresseusement la liste, c'est vrai, mais la liste était déjà complètement évaluée au moment où vous y arrivez!La phrase anglaise:
Se traduit par cette logique:
Le mot "mais" implique généralement une conjonction, en d'autres termes "et". De plus, «tous» se traduit par une conjonction de conditions: cette condition, et cette condition, et une autre condition. Le «non» inverse toute cette conjonction.
Je ne suis pas d'accord que la réponse acceptée. L'auteur a négligé d'appliquer l'interprétation la plus directe à la spécification et a négligé d'appliquer la loi de De Morgan pour simplifier l'expression à moins d'opérateurs:
tout en affirmant que la réponse est une "forme minimale".
la source
Cela revient
True
si une et une seule des trois conditions estTrue
. Probablement ce que vous vouliez dans votre exemple de code.la source
Qu'en est-il: (condition unique)
Remarquez, si vous autorisez également deux conditions, vous pouvez le faire
la source
1 <= bool(a) + bool(b) + bool(c) <= 2
.Pour être clair, vous voulez prendre votre décision en fonction de la quantité de paramètres logiques TRUE (en cas d'arguments de chaîne - non vides)?
Ensuite, vous avez pris une décision:
Maintenant, la logique est plus claire.
la source
Et pourquoi ne pas simplement les compter?
la source
Si cela ne vous dérange pas d'être un peu énigmatique, vous pouvez simplement lancer
0 < (a + b + c) < 3
ce qui reviendratrue
si vous avez entre une et deux déclarations vraies et false si toutes sont fausses ou aucune n'est fausse.Cela simplifie également si vous utilisez des fonctions pour évaluer les booléens car vous n'évaluez les variables qu'une seule fois et ce qui signifie que vous pouvez écrire les fonctions en ligne et que vous n'avez pas besoin de stocker temporairement les variables. (Exemple:.
0 < ( a(x) + b(x) + c(x) ) < 3
)la source
La question indique que vous avez besoin des trois arguments (a et b et c) ou aucun d'entre eux (pas (a ou b ou c))
Cela donne:
(a et b et c) ou non (a ou b ou c)
la source
Si je comprends bien, vous avez une fonction qui reçoit 3 arguments, mais si ce n'est pas le cas, elle fonctionnera avec le comportement par défaut. Puisque vous n'avez pas expliqué ce qui devrait se passer lorsque 1 ou 2 arguments sont fournis, je suppose qu'il devrait simplement faire le comportement par défaut. Dans ce cas, je pense que vous trouverez la réponse suivante très avantageuse:
Cependant, si vous souhaitez que 1 ou 2 arguments soient traités différemment:
Remarque: cela suppose que les
False
valeurs " " ne seront pas transmises à cette méthode.la source
Si vous travaillez avec un itérateur de conditions, l'accès peut être lent. Mais vous n'avez pas besoin d'accéder à chaque élément plus d'une fois, et vous n'avez pas toujours besoin de tout lire. Voici une solution qui fonctionnera avec des générateurs infinis:
la source
Quand chaque donné
bool
estTrue
, ou quand chaque donnébool
estFalse
...ils sont tous égaux l'un à l'autre!
Il suffit donc de trouver deux éléments qui s'évaluent à des
bool
s différentspour savoir qu'il y en a au moins un
True
et au moins unFalse
.Ma solution courte:
Je crois qu'il court-circuits, car AFAIK
a==b==c
est égala==b and b==c
.Ma solution généralisée:
J'ai également écrit du code traitant de plusieurs itérables, mais je l'ai supprimé d'ici car je pense que c'est inutile. Il est cependant toujours disponible ici .
la source
Ceci est essentiellement un « certains (mais pas tous) » fonctionnalité (en contraste avec le
any()
etall()
fonctions intégrées ).Cela implique qu'il devrait y avoir des
False
s et desTrue
s parmi les résultats. Par conséquent, vous pouvez effectuer les opérations suivantes:Un avantage de ce code est que vous n'avez besoin de parcourir qu'une seule fois les éléments (booléens) résultants.
Un inconvénient est que toutes ces expressions de vérité sont toujours évaluées et ne font pas de court-circuit comme les opérateurs
or
/and
.la source
.issuperset
plutôt que de simplement vérifier la longueur 2,bool
ne peut pas renvoyer autre chose que True et False de toute façon. Pourquoi attribuer un lambda (lecture: fonction anonyme) à un nom au lieu d'utiliser simplement une def?return
si vous l'utilisezdef
. Je pense que la généralité de cette solution est agréable. il n'est pas nécessaire de se limiter aux booléens, la question est essentiellement "comment puis-je m'assurer que tous ces éléments apparaissent dans ma liste". pourquoiset
si vous n'avez pas besoin de la mutabilité? plus d'immuabilité est toujours meilleure si vous n'avez pas besoin de la performance.tee
itertools.tee
mais 1) je cherchais un one-liner qui était simple / assez petit pour justifier un copier-coller, 2) vous avez déjà donné une réponse qui utilise cette technique :-)