Я пишу систему безопасности, которая запрещает доступ неавторизованным пользователям.
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.")
Он предоставляет доступ авторизованным пользователям, как и ожидалось, но также позволяет неавторизованным пользователям!
Hello. Please enter your name:
Bob
Access granted.
Почему это происходит? Я прямо заявил, что предоставляю доступ только name
Кевину, Джону или Инбару. Я тоже пробовал обратную логику if "Kevin" or "Jon" or "Inbar" == name
, но результат тот же.
x or y in z
,x and y in z
,x != y and z
и некоторые другие. Хотя это не совсем то же самое, что и этот вопрос, основная причина у них одинакова. Просто хотел указать на это на случай, если кто-то закрыл свой вопрос как дубликат этого и не был уверен, насколько это актуально для них.Ответы:
Во многих случаях Python выглядит и ведет себя как естественный английский, но это тот случай, когда эта абстракция терпит неудачу. Люди могут использовать контекстные подсказки, чтобы определить, что «Джон» и «Инбар» являются объектами, соединенными с глаголом «равно», но интерпретатор Python более буквальный.
логически эквивалентно:
Что для пользователя Боба эквивалентно:
or
Оператор выбирает первый аргумент с положительным значением истинности :И поскольку «Джон» имеет положительное значение истинности,
if
блок выполняется. Это то, что вызывает печать «Доступ предоставлен» независимо от указанного имени.Все эти рассуждения также применимы к выражению
if "Kevin" or "Jon" or "Inbar" == name
. первое значение,"Kevin"
истинно, поэтомуif
блок выполняется.Есть два распространенных способа правильно построить это условие.
Используйте несколько
==
операторов для явной проверки каждого значения:if name == "Kevin" or name == "Jon" or name == "Inbar":
Составьте последовательность допустимых значений и используйте
in
оператор для проверки принадлежности:if name in {"Kevin", "Jon", "Inbar"}:
В целом из двух следует предпочесть второе, так как его легче читать, а также быстрее:
Для тех, кому может понадобиться доказательство,
if a == b or c or d or e: ...
которое действительно разбирается таким образом. Встроенныйast
модуль дает ответ:Таким образом,
test
изif
заявления выглядит следующим образом :Как можно видеть, это логический оператор
or
применяется к несколькимvalues
, а именно,a == b
иc
,d
иe
.источник
("Kevin", "Jon", "Inbar")
вместо набора{"Kevin", "Jon", "Inbar"}
?a in {b, c, d}
примерно в два раза быстрее, чемa in (b, c, d)
на моей машине. Есть над чем подумать, если это критичный для производительности фрагмент кода.frozenset
вместо этого делает его , поэтому накладные расходы на построение набора отсутствуют.dis.dis(compile("1 in {1, 2, 3}", '<stdin>', 'eval'))
Простая инженерная задача, давайте немного дальше.
Но унаследованный от языка C Python оценивает логическое значение ненулевого целого числа как True.
Теперь Python основывается на этой логике и позволяет использовать логические литералы, такие как или на целых числах, и т.
в заключение
Правильный способ написать это:
В целях безопасности я также рекомендую вам не кодировать жестко пароли.
источник
Есть 3 проверки условий в
if name == "Kevin" or "Jon" or "Inbar":
и этот оператор if эквивалентен
Поскольку
elif "Jon"
всегда будет истинным, доступ предоставляется любому пользователюРешение
Вы можете использовать любой из приведенных ниже способов
Быстро
Медленный
Медленный + ненужный код
источник