Python 为什么`a == b or c or d` 总是评估为真?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/20002503/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Why does `a == b or c or d` always evaluate to True?
提问by Kevin
I am writing a security system that denies access to unauthorized users.
我正在编写一个拒绝未经授权用户访问的安全系统。
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.")
It grants access to authorized users as expected, but it also lets in unauthorized users!
它按预期向授权用户授予访问权限,但也允许未经授权的用户进入!
Hello. Please enter your name:
Bob
Access granted.
Why does this occur? I've plainly stated to only grant access when nameequals Kevin, Jon, or Inbar. I have also tried the opposite logic, if "Kevin" or "Jon" or "Inbar" == name, but the result is the same.
为什么会出现这种情况?我已经明确声明只在name等于 Kevin、Jon 或 Inbar时授予访问权限。我也尝试过相反的逻辑if "Kevin" or "Jon" or "Inbar" == name,但结果是一样的。
回答by Kevin
In many cases, Python looks and behaves like natural English, but this is one case where that abstraction fails. People can use context clues to determine that "Jon" and "Inbar" are objects joined to the verb "equals", but the Python interpreter is more literal minded.
在许多情况下,Python 的外观和行为都像自然英语,但这是抽象失败的一种情况。人们可以使用上下文线索来确定“Jon”和“Inbar”是连接到动词“equals”的对象,但 Python 解释器更注重字面意思。
if name == "Kevin" or "Jon" or "Inbar":
is logically equivalent to:
在逻辑上等同于:
if (name == "Kevin") or ("Jon") or ("Inbar"):
Which, for user Bob, is equivalent to:
对于用户 Bob,这相当于:
if (False) or ("Jon") or ("Inbar"):
The oroperator chooses the first argument with a positive truth value:
该or运营商选择以积极的第一个参数真值:
if ("Jon"):
And since "Jon" has a positive truth value, the ifblock executes. That is what causes "Access granted" to be printed regardless of the name given.
并且由于“Jon”具有正真值,因此if块会执行。这就是导致无论给出的名称如何都会打印“授予访问权限”的原因。
All of this reasoning also applies to the expression if "Kevin" or "Jon" or "Inbar" == name. the first value, "Kevin", is true, so the ifblock executes.
所有这些推理也适用于表达式if "Kevin" or "Jon" or "Inbar" == name。第一个值"Kevin"为真,因此if块执行。
There are two common ways to properly construct this conditional.
有两种常见的方法可以正确构造此条件。
Use multiple
==operators to explicitly check against each value:if name == "Kevin" or name == "Jon" or name == "Inbar":Compose a sequence of valid values, and use the
inoperator to test for membership:if name in {"Kevin", "Jon", "Inbar"}:
使用多个
==运算符显式检查每个值:if name == "Kevin" or name == "Jon" or name == "Inbar":组成一系列有效值,并使用
in运算符来测试成员资格:if name in {"Kevin", "Jon", "Inbar"}:
In general of the two the second should be preferred as it's easier to read and also faster:
一般来说,第二个应该是首选,因为它更容易阅读,也更快:
>>> import timeit
>>> timeit.timeit('name == "Kevin" or name == "Jon" or name == "Inbar"', setup="name='Inbar'")
0.4247764749999945
>>> timeit.timeit('name in {"Kevin", "Jon", "Inbar"}', setup="name='Inbar'")
0.18493307199999265
回答by user1854182
Simple engineering problem, let's simply it a bit further.
简单的工程问题,让我们再深入一点。
In [1]: a,b,c,d=1,2,3,4
In [2]: a==b
Out[2]: False
But, inherited from the language C, Python evaluates the logical value of a non zero integer as True.
但是,继承自 C 语言,Python 将非零整数的逻辑值计算为 True。
In [11]: if 3:
...: print ("yey")
...:
yey
Now, Python builds on that logic and let you use logic literals such as or on integers, and so
现在,Python 建立在该逻辑之上,并允许您使用逻辑文字,例如 或 整数,等等
In [9]: False or 3
Out[9]: 3
Finally
最后
In [4]: a==b or c or d
Out[4]: 3
The proper way to write it would be:
正确的写法是:
In [13]: if a in (b,c,d):
...: print('Access granted')
For safety I'd also suggest you don't hard code passwords.
为了安全起见,我还建议您不要对密码进行硬编码。

