Piszę system bezpieczeństwa, który odmawia dostępu nieautoryzowanym użytkownikom.
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.")
Zapewnia dostęp upoważnionym użytkownikom zgodnie z oczekiwaniami, ale także umożliwia dostęp nieautoryzowanym użytkownikom!
Hello. Please enter your name:
Bob
Access granted.
Dlaczego tak się dzieje? Wyraźnie stwierdziłem, że udzielam dostępu tylko wtedy, gdy name
jest równy Kevinowi, Jonowi lub Inbarowi. Próbowałem też odwrotnej logiki if "Kevin" or "Jon" or "Inbar" == name
, ale wynik jest taki sam.
x or y in z
,x and y in z
,x != y and z
i kilka innych. Chociaż nie jest to dokładnie identyczne z tym pytaniem, główna przyczyna jest taka sama dla wszystkich. Chciałem tylko zwrócić uwagę na to, na wypadek gdyby ktoś zamknął swoje pytanie jako duplikat tego i nie był pewien, jakie ma dla niego znaczenie.Odpowiedzi:
W wielu przypadkach Python wygląda i zachowuje się jak naturalny angielski, ale jest to jeden przypadek, w którym ta abstrakcja zawodzi. Ludzie mogą używać wskazówek kontekstowych, aby określić, że „Jon” i „Inbar” są obiektami połączonymi z czasownikiem „równa się”, ale interpreter Pythona jest bardziej dosłowny.
jest logicznie równoważne z:
Co dla użytkownika Bob jest równoważne z:
or
Operator wybiera pierwszy argument z pozytywnej wartości logicznej :A ponieważ „Jon” ma dodatnią wartość prawdy,
if
blok jest wykonywany. To właśnie powoduje, że "Przyznany dostęp" jest drukowany niezależnie od podanej nazwy.Całe to rozumowanie odnosi się również do wyrażenia
if "Kevin" or "Jon" or "Inbar" == name
. pierwsza wartość"Kevin"
to prawda, więcif
blok jest wykonywany.Istnieją dwa typowe sposoby prawidłowego skonstruowania tego warunku.
Użyj wielu
==
operatorów, aby jawnie sprawdzić każdą wartość:if name == "Kevin" or name == "Jon" or name == "Inbar":
Utwórz sekwencję prawidłowych wartości i użyj
in
operatora, aby przetestować członkostwo:if name in {"Kevin", "Jon", "Inbar"}:
Ogólnie rzecz biorąc, druga powinna być preferowana, ponieważ jest łatwiejsza do odczytania, a także szybsza:
Dla tych, którzy mogą chcieć dowodu, który
if a == b or c or d or e: ...
rzeczywiście jest analizowany w ten sposób. Wbudowanyast
moduł dostarcza odpowiedzi:Więc
test
zif
wyglądem rachunku, takich jak ten:Jak widać, jest to operator logiczna
or
zastosowana do wielokrotnegovalues
, a mianowicie,a == b
ic
,d
ie
.źródło
("Kevin", "Jon", "Inbar")
zamiast zestawu{"Kevin", "Jon", "Inbar"}
?a in {b, c, d}
jest około dwa razy szybsza niża in (b, c, d)
na moim komputerze. Coś do przemyślenia, jeśli jest to fragment kodu krytyczny dla wydajności.frozenset
zamiast tego, więc narzut zestawu konstrukcyjnego nie istnieje.dis.dis(compile("1 in {1, 2, 3}", '<stdin>', 'eval'))
Prosty problem inżynieryjny, przejdźmy dalej.
Ale, odziedziczony z języka C, Python ocenia wartość logiczną niezerowej liczby całkowitej jako True.
Teraz Python opiera się na tej logice i pozwala używać literałów logicznych, takich jak lub na liczbach całkowitych, i tak
Wreszcie
Prawidłowy sposób zapisu to:
Ze względów bezpieczeństwa sugerowałbym również, aby nie kodować haseł na stałe.
źródło
Istnieją 3 warunki sprawdzania
if name == "Kevin" or "Jon" or "Inbar":
i to jeśli instrukcja jest równoważna
Ponieważ
elif "Jon"
zawsze będzie prawdziwe, więc dostęp do każdego użytkownika jest przyznanyRozwiązanie
Możesz użyć jednej z poniższych metod
Szybki
Powolny
Powolny + niepotrzebny kod
źródło