Ich schreibe ein Sicherheitssystem, das nicht autorisierten Benutzern den Zugriff verweigert.
import sys
print("Hello. Please enter your name:")
name = sys.stdin.readline().strip()
if name == "Kevin" or "Jon" or "Inbar":
print("Access granted.")
else:
print("Access denied.")
Es gewährt autorisierten Benutzern erwartungsgemäß Zugriff, lässt aber auch nicht autorisierte Benutzer zu!
Hello. Please enter your name:
Bob
Access granted.
Warum tritt das auf? Ich habe klar gesagt, dass ich nur dann Zugriff gewähren soll, wenn name
Kevin, Jon oder Inbar gleichgestellt sind. Ich habe auch die entgegengesetzte Logik ausprobiert if "Kevin" or "Jon" or "Inbar" == name
, aber das Ergebnis ist das gleiche.
x or y in z
,x and y in z
,x != y and z
und ein paar andere. Obwohl dies nicht genau mit dieser Frage identisch ist, ist die Grundursache für alle gleich. Ich wollte nur darauf hinweisen, falls jemand seine Frage als Duplikat davon geschlossen hat und nicht sicher war, wie relevant sie für ihn ist.Antworten:
In vielen Fällen sieht Python wie natürliches Englisch aus und verhält sich auch so. In diesem Fall schlägt diese Abstraktion jedoch fehl. Menschen können Kontexthinweise verwenden, um festzustellen, dass "Jon" und "Inbar" Objekte sind, die mit dem Verb "gleich" verbunden sind, aber der Python-Interpreter ist wörtlicher.
ist logisch äquivalent zu:
Was für Benutzer Bob gleichbedeutend ist mit:
Der
or
Operator wählt das erste Argument mit einem positiven Wahrheitswert :Und da "Jon" einen positiven Wahrheitswert hat, wird der
if
Block ausgeführt. Aus diesem Grund wird "Zugriff gewährt" unabhängig vom angegebenen Namen gedruckt.All diese Überlegungen gelten auch für den Ausdruck
if "Kevin" or "Jon" or "Inbar" == name
. Der erste Wert"Kevin"
ist true, daher wird derif
Block ausgeführt.Es gibt zwei übliche Möglichkeiten, diese Bedingung richtig zu konstruieren.
Verwenden Sie mehrere
==
Operatoren, um explizit mit jedem Wert zu vergleichen:if name == "Kevin" or name == "Jon" or name == "Inbar":
Erstellen Sie eine Folge gültiger Werte und
in
testen Sie mit dem Operator die Mitgliedschaft:if name in {"Kevin", "Jon", "Inbar"}:
Im Allgemeinen sollte die zweite bevorzugt werden, da sie leichter zu lesen und auch schneller ist:
Für diejenigen, die Beweise wollen,
if a == b or c or d or e: ...
die tatsächlich so analysiert werden. Das eingebauteast
Modul bietet eine Antwort:So ist die
test
derif
Aussage sieht wie folgt aus :Wie man sehen kann, ist es der Booleschen Operator
or
auf mehr angewandtvalues
, nämlicha == b
undc
,d
unde
.quelle
("Kevin", "Jon", "Inbar")
anstelle eines Satzes zu wählen{"Kevin", "Jon", "Inbar"}
?a in {b, c, d}
ist ungefähr doppelt so schnell wiea in (b, c, d)
auf meinem Computer. Denken Sie darüber nach, ob dies ein leistungskritischer Code ist.frozenset
stattdessen zu einer Konstante , sodass der Overhead der Konstruktionsmenge nicht vorhanden ist.dis.dis(compile("1 in {1, 2, 3}", '<stdin>', 'eval'))
Einfaches Engineering-Problem, lassen Sie es uns einfach etwas weiter gehen.
Python, das von der Sprache C geerbt wurde, wertet den logischen Wert einer Ganzzahl ungleich Null als True aus.
Jetzt baut Python auf dieser Logik auf und lässt Sie Logikliterale wie oder auf Ganzzahlen usw. verwenden
Schließlich
Die richtige Art, es zu schreiben, wäre:
Aus Sicherheitsgründen würde ich auch vorschlagen, dass Sie keine festen Kennwörter verwenden.
quelle
Es gibt 3 Zustandsüberprüfungen
if name == "Kevin" or "Jon" or "Inbar":
und diese if-Anweisung ist äquivalent zu
Da
elif "Jon"
immer wahr sein wird, wird der Zugriff auf jeden Benutzer gewährtLösung
Sie können eine der folgenden Methoden verwenden
Schnell
Langsam
Langsam + Unnötiger Code
quelle