我正在编写一个拒绝未经授权用户访问的安全系统。
name = input("Hello. Please enter your name: ")
if name == "Kevin" or "Jon" or "Inbar":
print("Access granted.")
else:
print("Access denied.")
它按预期授予授权用户访问权限,但它也允许未经授权的用户访问!
Hello. Please enter your name: Bob
Access granted.
为什么会发生这种情况?我已明确声明仅在 name
等于 Kevin、Jon 或 Inbar 时授予访问权限。我也试过相反的逻辑, if "Kevin" or "Jon" or "Inbar" == name
,但结果是一样的。
这个问题旨在作为这个非常常见问题的规范重复目标。还有另一个热门问题 How to test multiple variables for equality against a single value? 具有相同的基本问题,但比较目标相反。这个问题不应该作为那个问题的重复而关闭,因为这个问题是 Python 新手遇到的,他们可能难以将反向问题中的知识应用于他们的问题。
原文由 Kevin 发布,翻译遵循 CC BY-SA 4.0 许可协议
在许多情况下,Python 看起来和行为都像自然英语,但这是抽象失败的一种情况。人们可以使用上下文线索来确定“Jon”和“Inbar”是连接到动词“equals”的宾语,但 Python 解释器更注重字面意思。
在逻辑上等同于:
对于用户 Bob,这相当于:
or
运算符选择具有正 真值 的第一个参数:由于“Jon”具有正真值,
if
块执行。这就是导致无论给定名称如何都打印“已授予访问权限”的原因。所有这些推理也适用于表达式
if "Kevin" or "Jon" or "Inbar" == name
。第一个值"Kevin"
为真,因此if
块执行。有两种常见的方法可以正确构造此条件。
==
运算符明确检查每个值:in
运算符来测试成员资格:一般来说,第二个应该是首选,因为它更容易阅读,也更快:
对于那些可能想要证明
if a == b or c or d or e: ...
确实是这样解析的人。内置的ast
模块提供了一个答案:可以看到,它是布尔运算符
or
应用于四个子表达式: comparisona == b
;和简单的表达式c
,d
和e
。