为什么`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块执行。


有两种常见的方法来正确构造这个条件。

  1. 使用多个==运算符来显式检查每个值:
    if name == "Kevin" or name == "Jon" or name == "Inbar":

  2. 撰写一系列有效值,并使用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