Ich habe ein Python-Skript, das entweder null oder drei Befehlszeilenargumente empfangen kann. (Entweder wird das Standardverhalten ausgeführt oder es müssen alle drei angegebenen Werte angegeben werden.)
Was ist die ideale Syntax für so etwas wie:
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
quelle
quelle
len(sys.argv)
wird immer mindestens 1 sein: Es enthält die ausführbare Datei alsargv[0]
.if not (a and b and c)
Könntest du nicht einfach sagen (null Argumente) und dannif a and b and c
(alle drei Argumente)?Antworten:
Wenn Sie eine minimale Form meinen, gehen Sie wie folgt vor:
Welches übersetzt den Titel Ihrer Frage.
UPDATE: Wie von Volatility und Supr richtig gesagt, können Sie das Gesetz von De Morgan anwenden und ein Äquivalent erhalten:
Mein Rat ist, die Form zu verwenden, die für Sie und andere Programmierer wichtiger ist. Das erste bedeutet "es gibt etwas Falsches, aber auch etwas Wahres" , das zweite "Es gibt etwas Wahres, aber nicht alles" . Wenn ich dies in der Hardware optimieren oder tun würde, würde ich die zweite wählen, hier nur die am besten lesbare auswählen (auch unter Berücksichtigung der Bedingungen, die Sie testen werden, und ihrer Namen). Ich habe den ersten ausgewählt.
quelle
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)
, um perfekt zum Titel zu passen;)if any([a,b,c]) and not all([a,b,c])
Wie wäre es mit:
Andere Variante:
quelle
sum(conditions)
kann schief gehen, wenn einer von ihnen2
zum Beispiel zurückkehrt, was istTrue
.sum(map(bool, conditions))
Diese Frage hatte bereits viele hoch bewertete Antworten und eine akzeptierte Antwort, aber alle waren bisher durch verschiedene Ausdrucksmöglichkeiten des booleschen Problems abgelenkt und haben einen entscheidenden Punkt übersehen:
Diese Logik sollte nicht in erster Linie in der Verantwortung Ihres Codes liegen , sondern vom
argparse
Modulbehandelt werden. Schreiben Sie keine komplexe if-Anweisung, sondern richten Sie Ihren Argument-Parser lieber wie folgt ein:Und ja, es sollte eine Option sein, kein Positionsargument, denn es ist schließlich optional .
bearbeitet: Um das Problem von LarsH in den Kommentaren anzusprechen, finden Sie unten ein Beispiel dafür, wie Sie es schreiben könnten, wenn Sie sicher wären, dass Sie die Schnittstelle mit 3 oder 0 Positionsargumenten haben möchten. Ich bin der Meinung, dass die vorherige Benutzeroberfläche einen besseren Stil hat, da optionale Argumente Optionen sein sollten , aber der Vollständigkeit halber hier ein alternativer Ansatz. Beachten Sie das überschreibende kwarg
usage
beim Erstellen Ihres Parsers, daargparse
sonst automatisch eine irreführende Verwendungsnachricht generiert wird!Hier einige Anwendungsbeispiele:
quelle
Ich würde gehen für:
Ich denke, dies sollte ziemlich effizient kurzschließen
Erläuterung
Wenn Sie
conds
einen Iterator erstellen, wird die erste Verwendung vonany
kurzgeschlossen und der Iterator zeigt auf das nächste Element, wenn ein Element wahr ist. Andernfalls wird die gesamte Liste verbraucht und seinFalse
. Der nächsteany
nimmt die verbleibenden Elemente in der Iterable und stellt sicher, dass es keine anderen wahren Werte gibt ... Wenn ja, kann die gesamte Aussage nicht wahr sein, daher gibt es kein einziges Element (also Kurzschlüsse) nochmal). Der letzteany
wird entweder zurückkehrenFalse
oder das iterable erschöpfen und seinTrue
.Hinweis: Die obige Prüfung prüft, ob nur eine einzige Bedingung festgelegt ist
Wenn Sie überprüfen möchten, ob ein oder mehrere Elemente, aber nicht jedes Element festgelegt ist, können Sie Folgendes verwenden:
quelle
[a, b, c] = [True, True, False]
sollte Ihr Code nicht "gedruckt" werdenFalse
, während die erwartete Ausgabe erfolgtTrue
?iter
.any
undall
wird die Liste träge konsumieren, stimmt, aber die Liste wurde bereits vollständig ausgewertet, als Sie dort ankommen!Der englische Satz:
Übersetzt in diese Logik:
Das Wort "aber" impliziert normalerweise eine Konjunktion, mit anderen Worten "und". Darüber hinaus bedeutet "alle von ihnen" eine Verbindung von Bedingungen: diese Bedingung und diese Bedingung und andere Bedingung. Das "nicht" invertiert diese gesamte Konjunktion.
Ich bin nicht damit einverstanden, dass die Antwort akzeptiert. Der Autor hat es versäumt, die einfachste Interpretation auf die Spezifikation anzuwenden, und es versäumt, das De-Morgan-Gesetz anzuwenden, um den Ausdruck auf weniger Operatoren zu vereinfachen:
während behauptet wird, dass die Antwort eine "minimale Form" ist.
quelle
Dies wird zurückgegeben,
True
wenn eine und nur eine der drei Bedingungen erfüllt istTrue
. Wahrscheinlich das, was Sie in Ihrem Beispielcode wollten.quelle
Was ist mit: (einzigartiger Zustand)
Beachten Sie, wenn Sie auch zwei Bedingungen zulassen, können Sie dies tun
quelle
1 <= bool(a) + bool(b) + bool(c) <= 2
.Um klar zu sein, möchten Sie Ihre Entscheidung basierend darauf treffen, wie viele der Parameter logisch WAHR sind (im Fall von Zeichenfolgenargumenten - nicht leer)?
Dann haben Sie eine Entscheidung getroffen:
Jetzt ist die Logik klarer.
quelle
Und warum nicht einfach zählen?
quelle
Wenn es Ihnen nichts ausmacht, ein bisschen kryptisch zu sein, können Sie einfach rollen, mit
0 < (a + b + c) < 3
dem Sie zurückkehrentrue
wenn Sie zwischen einer und zwei wahre Aussagen haben, und falsch, wenn alle falsch sind oder keine falsch ist.Dies vereinfacht sich auch, wenn Sie Funktionen zum Auswerten der Bools verwenden, da Sie die Variablen nur einmal auswerten. Dies bedeutet, dass Sie die Funktionen inline schreiben können und die Variablen nicht vorübergehend speichern müssen. (Beispiel :
0 < ( a(x) + b(x) + c(x) ) < 3
.)quelle
Die Frage besagt, dass Sie entweder alle drei Argumente (a und b und c) oder keines von ihnen (nicht (a oder b oder c)) benötigen.
Das gibt:
(a und b und c) oder nicht (a oder b oder c)
quelle
Soweit ich weiß, haben Sie eine Funktion, die 3 Argumente empfängt. Wenn dies nicht der Fall ist, wird sie mit dem Standardverhalten ausgeführt. Da Sie nicht erklärt haben, was passieren soll, wenn 1 oder 2 Argumente angegeben werden, gehe ich davon aus, dass es einfach das Standardverhalten ausführen sollte. In diesem Fall finde ich die folgende Antwort sehr vorteilhaft:
Wenn Sie jedoch möchten, dass 1 oder 2 Argumente unterschiedlich behandelt werden:
Hinweis: Dies setzt voraus, dass "
False
" Werte nicht an diese Methode übergeben werden.quelle
Wenn Sie mit einem Iterator von Bedingungen arbeiten, kann der Zugriff langsam sein. Sie müssen jedoch nicht mehr als einmal auf jedes Element zugreifen, und Sie müssen nicht immer alles lesen. Hier ist eine Lösung, die mit unendlichen Generatoren funktioniert:
quelle
Wenn jedes gegeben
bool
istTrue
oder wenn jedes gegebenbool
istFalse
...sie alle gleich!
Wir müssen also nur zwei Elemente finden, die unterschiedliche
bool
Werte ergeben, umzu wissen, dass es mindestens eines
True
und mindestens eines gibtFalse
.Meine kurze Lösung:
Ich glaube es schließt kurz, weil AFAIK
a==b==c
gleich ista==b and b==c
.Meine verallgemeinerte Lösung:
Ich habe auch Code geschrieben, der sich mit mehreren Iterablen befasst, aber ich habe ihn von hier gelöscht, weil ich denke, dass er sinnlos ist. Es ist jedoch noch hier verfügbar .
quelle
Dies ist im Grunde eine "einige (aber nicht alle)" Funktionalität (im Gegensatz zu
any()
undall()
eingebauten Funktionen).Dies impliziert, dass es
False
s undTrue
s unter den Ergebnissen geben sollte. Daher können Sie Folgendes tun:Ein Vorteil dieses Codes besteht darin, dass Sie die resultierenden (booleschen) Elemente nur einmal durchlaufen müssen.
Ein Nachteil ist, dass alle diese Wahrheitsausdrücke immer ausgewertet werden und nicht wie die / -Operatoren kurzschließen .
or
and
quelle
.issuperset
anstatt nur nach Länge 2 zu suchen,bool
kann ich sowieso nichts anderes als Wahr und Falsch zurückgeben. Warum einem Namen ein Lambda (sprich: anonyme Funktion) zuweisen, anstatt nur ein Def zu verwenden?return
wenn Sie sie verwendendef
. Ich finde die Allgemeinheit dieser Lösung gut. Es ist nicht notwendig, uns auf Boolesche Werte zu beschränken. Die Frage lautet im Wesentlichen: "Wie stelle ich sicher, dass alle diese Elemente in meiner Liste vorkommen?" Warum,set
wenn Sie die Veränderlichkeit nicht brauchen? Mehr Unveränderlichkeit ist immer besser, wenn Sie die Leistung nicht benötigen.tee
itertools.tee
aber 1) ich suchte nach einem Einzeiler, der einfach / klein genug war, um das Einfügen von Kopien zu rechtfertigen, 2) Sie gaben bereits eine Antwort, die diese Technik verwendet :-)