2013-11-15 81 views
69

我正在写一个拒绝未经授权用户访问的安全系统。为什么`a == b或c或d`总是评估为True?

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,但结果是一样的。

+0

写作条件最常用的写法是'如果名字在[“凯文”,“乔恩”,“Inbar”]:'' – djinn

回答

103

在许多情况下,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操作员选择的第一个参数具有正truth value

if ("Jon"): 

并且由于“Jon”具有正的真值,因此将执行if块。不管名称如何,这就是“授予访问权限”的原因。

所有这些推理也适用于表达if "Kevin" or "Jon" or "Inbar" == name。第一个值"Kevin"为true,因此将执行if块。


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

  1. 使用多个==运营商明确检查对每个值:
    if name == "Kevin" or name == "Jon" or name == "Inbar":

  2. 撰写有效值的序列,并使用in操作来测试成员:
    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 
相关问题