为什么`a == b或c或d`总是评估为真?
我正在写一个安全系统,拒绝未经授权的用户访问。
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
等于Kevin,Jon或Inbar时才允许访问。 我也尝试了相反的逻辑, if "Kevin" or "Jon" or "Inbar" == name
,但结果是一样的。
在许多情况下,Python的外观和行为与自然英语相似,但这是抽象失败的一种情况。 人们可以使用上下文线索来确定“Jon”和“Inbar”是连接到动词“equals”的对象,但是Python解释器更具有文字意义。
if name == "Kevin" or "Jon" or "Inbar":
在逻辑上相当于:
if (name == "Kevin") or ("Jon") or ("Inbar"):
对于用户Bob来说,它相当于:
if (False) or ("Jon") or ("Inbar"):
or
运算符select具有正确的真值的第一个参数:
if ("Jon"):
而且由于“乔恩”具有肯定的真值,所以if
块执行。 这是什么原因导致“访问授予”被打印,无论给出的名称。
所有这些推理也适用于expression式, if "Kevin" or "Jon" or "Inbar" == name
。 第一个值"Kevin"
是真的,所以if
块执行。
有两种常见的方法来正确构造这个条件。
-
使用多个
==
运算符来显式检查每个值:
if name == "Kevin" or name == "Jon" or name == "Inbar":
-
撰写一系列有效值,并使用
in
运算符来testing成员资格:
if name in ("Kevin", "Jon", "Inbar"):
一般情况下,第二个应该是首选,因为它更容易阅读,也更快:
In [1]: name = "Inbar" In [2]: %timeit name == "Keven" or name == "Jon" or name == "Inbar" 10000000 loops, best of 3: 116 ns per loop In [3]: %timeit name in ("Keven", "Jon", "Inbar") 10000000 loops, best of 3: 65.2 ns per loop