为什么要“ a == x或y或z”总是评估为真?我如何比较“ a”所有这些?
我正在编写一个安全系统,该系统拒绝访问未经授权的用户。
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.
为什么会发生这种情况?我很清楚地说,仅当名称
等于Kevin,Jon或Inbar时才授予访问权限。我还尝试了相反的逻辑,如果“ kevin”或“ jon”或“ inbar” ==名称
,但结果是相同的。
这个问题旨在作为这个非常常见问题的规范重复目标。还有另一个流行的问题如何测试多个变量的平等变量以抗A单个值?存在相同的基本问题,但是比较目标是逆转的。这个问题不应作为该问题的重复,因为新移民遇到了这个问题,而Python可能会在
而不是==
,这里有解决方案:如何测试列表中多个值的成员
I am writing a security system that denies access to unauthorized users.
name = input("Hello. Please enter your name: ")
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 name
equals Kevin, Jon, or Inbar. I have also tried the opposite logic, if "Kevin" or "Jon" or "Inbar" == name
, but the result is the same.
This question is intended as the canonical duplicate target of this very common problem. There is another popular question How to test multiple variables for equality against a single value? that has the same fundamental problem, but the comparison targets are reversed. This question should not be closed as a duplicate of that one as this problem is encountered by newcomers to Python who might have difficulties applying the knowledge from the reversed question to their problem.
For in
instead of ==
, there are solutions here: How to test the membership of multiple values in a list
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(8)
方法
是数据科学家如何处理此问题的
最简单方法是消除比较操作员的需求并使用列表。这在安全系统上看起来令人印象深刻,因为您学会访问ORMS。
或者,您可以类似于上面的 extike 相同的代码,只需将注册用户的列表放入其自己的列表中:
如果您想安全地完成此协议而没有攻击风险,请设置双参数。这将检查您的迷你摩托<代码>第一个和
最后
名称字段,以及password
或秘密问题
钥匙。如果您想有效地懒惰的用户凭据而无需哈希:循环将消耗 ,可以节省系统和能量,
则 可以将对象排序。迭代列表:
可以从任何角度解决此问题:内存管理,安全性,或者仅通过有机列表或包装ORM解决。
Approaches
How a data scientist approaches this problem
The simplest way possible is to eliminate the need for comparison operators and use a list. This looks impressive on security systems because you learn to access ORMs.
Or, you can resemble the exact same code above, just put the list of registered users in their own list:
If you wanted to complete this protocol safely without the risk of attack, set up double parameters. This would check your mini-ORM for
first
andlast
name fields, as well as apassword
orsecret question
key. Objects can be sorted like this if you want to efficiently lazy-load user credentials without hashing:The loop will consume only the yielded values to save time and energy on your system:
You can then do something with the iterated list:
This problem can be approached from any angle: memory management, security, or simply by an organic list or packaged ORM.
在许多情况下,Python的外观和行为就像天然英语一样,但这是该抽象失败的一种情况。人们可以使用上下文线索来确定“ Jon”和“ Inbar”是动词“等于”的对象,但是Python的解释器更为字面意义。
在逻辑上等同于:
对于用户bob而言,它等效于:
或
operator 选择第一个操作系统那就是“ truthy” ,即如果条件(或最后一个,如果没有一个是“真实的”):乔恩是真实的,如果块执行。这就是导致“授予”打印的“访问权限”的原因。
所有这些推理也适用于“ kevin”或“ jon”或“ inbar” ==名称的表达式
。第一个值<代码>“ kevin”
是正确的,因此 block execute 。有三种通用方法可以正确构建此条件。
使用多个
==
操作员明确检查每个值:构成有效值的集合(集合,列表或元组),并在操作员测试会员资格:
使用生成器表达式在循环中明确检查针对每个值:
一般而言第二应该是首选,因为它更容易阅读和更快:
对于那些可能想要证明
的人,如果a == b或c或d或e:...
确实是这样解析的。内置ast
模块提供了答案:正如人们所看到的,是布尔操作员
或
应用于四个子表达式:比较a == b
a == b < /代码>;和简单的表达式
c
,d
和e
。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.
is logically equivalent to:
Which, for user Bob, is equivalent to:
The
or
operator chooses the first operand that is "truthy", i.e. which would satisfy anif
condition (or the last one, if none of them are "truthy"):Since "Jon" is truthy, the
if
block executes. That is what causes "Access granted" to be printed regardless of the name given.All of this reasoning also applies to the expression
if "Kevin" or "Jon" or "Inbar" == name
. the first value,"Kevin"
, is true, so theif
block executes.There are three common ways to properly construct this conditional.
Use multiple
==
operators to explicitly check against each value:Compose a collection of valid values (a set, a list or a tuple for example), and use the
in
operator to test for membership:Use
any()
and a generator expression to explicitly check against each value in a loop:In general the second should be preferred as it's easier to read and also faster:
For those who may want proof that
if a == b or c or d or e: ...
is indeed parsed like this. The built-inast
module provides an answer:As one can see, it's the boolean operator
or
applied to four sub-expressions: comparisona == b
; and simple expressionsc
,d
, ande
.总结所有现有答案
(并添加了一些我的观点)
说明:
逻辑上等同于:
对于用户bob而言,它等同于:
注意:python评估任何非零整数的逻辑值为
> true
。因此,所有非空列表,集合,字符串等都是可评估的,并返回true
或
操作员选择具有正面真实价值的第一个参数。因此,“乔恩”具有正面的真实价值,而IF块执行,因为它现在等同于
导致“访问授予”的内容,而不论其名称输入如何。
解决方案:
解决方案1:使用多个
==
操作员明确检查每个值解决方案2:构成有效值的集合(一组,例如,列表或元组),并在中使用运算符中的
测试成员资格(更快,首选方法)
或
解决方案3:使用基本(并且不是很高效)
if-elif-else
结构Summarising all existing answers
(And adding a few of my points)
Explanation :
is logically equivalent to:
Which, for user Bob, is equivalent to:
NOTE : Python evaluates the logical value of any non-zero integer as
True
. Therefore, all Non-empty lists, sets, strings, etc. are evaluable and returnTrue
The
or
operator chooses the first argument with a positive truth value.Therefore, "Jon" has a positive truth value and the if block executes, since it is now equivalent to
That is what causes "Access granted" to be printed regardless of the name input.
Solutions :
Solution 1 : Use multiple
==
operators to explicitly check against each valueSolution 2 : Compose a collection of valid values (a set, a list or a tuple for example), and use the
in
operator to test for membership (faster, preferred method)OR
Solution 3 : Use the basic (and not very efficient)
if-elif-else
structure中有3个条件检查如果名称==“ kevin”或“ jon”或“ inbar”:
,此if语句等同于
自<<代码> elif“ jon” 将始终是正确的,因此可以访问任何用户的
解决方案,
下使用任何一种方法
您可以在 fast> fast
slow> slow
slow + slow + 不必要的代码
There are 3 condition checks in
if name == "Kevin" or "Jon" or "Inbar":
and this if statement is equivalent to
Since
elif "Jon"
will always be true so access to any user is grantedSolution
You can use any one method below
Fast
Slow
Slow + Unnecessary code
可以评估不超空列表,集合,字符串等,因此返回true。
因此,当您说:
您实际上是在说:
由于“ John”和“ Inbar”中的至少一个不是一个空字符串,因此整个表达式总是返回的!
解决方案:
或:
Not-empty lists, sets, strings, etc. are evaluable and, therefore, return True.
Therefore, when you say:
You are actually saying:
Since at least one of "John" and "Inbar" is not an empty string, the whole expression always returns True!
The solution:
or:
使用
匹配
/案例
在Python 3.10及以上python 3.10 在语言中添加了一个新的语法。它被正式描述为“结构模式匹配”,但大多数人根据语法称其为:“
匹配
/case
”。我们可以通过制作一个与所有接受的用户名匹配的“案例”,并使用“通配符” case
_ 代替
else
。因此:请注意,使用
|
而不是或
“组合”案例。这是一种特殊的语法:python 尝试计算“ kevin” | “乔恩” | “ inbar”
first(|
与字符串无效),而是解释整个行的不同,因为它以case 。
Using
match
/case
in Python 3.10 and abovePython 3.10 adds a new syntax to the language. It's officially described as "structural pattern matching", but most people call it according to the syntax: "
match
/case
".We can use this special syntax for an example like in the question, by making one "case" that matches all the accepted usernames, and using the "wildcard" case
_
in place of theelse
. Thus:Note that cases are "combined" using
|
, notor
. This is a special syntax: Python does not try to compute"Kevin" | "Jon" | "Inbar"
first (|
doesn't work with strings), but instead interprets the entire line differently because it starts withcase
.简单的工程问题,让我们简单地进一步。
但是,从语言C继承,Python评估非零整数的逻辑值为真实。
现在,Python建立在该逻辑上,让您使用逻辑文字,例如或在整数上,因此
最终
编写的正确方法是:
为了安全起见,我还建议您不要硬代码密码。
Simple engineering problem, let's simply it a bit further.
But, inherited from the language C, Python evaluates the logical value of a non zero integer as True.
Now, Python builds on that logic and let you use logic literals such as or on integers, and so
Finally
The proper way to write it would be:
For safety I'd also suggest you don't hard code passwords.
除了其他一些相当稀有的 Walrus操作员的有用案例已经提到了。这也往往也是一个有用的情况。
之所以起作用,是因为
如果说明<-Statement < /code>
单独读取。因此
(v:= calc_value())
被执行,并将值分配给v
,如果第一次失败,则在不同条件或计算的名称空间中仍然具有v 。Besides some other rather rarer useful cases for the walrus operator already mentioned. This also tend to be a useful case as well.
This works because each part of the
if-statement
is read separately. So(v := calc_value())
is executed and a value is assigned tov
and if the first fails, you still have v in the namespace for different conditions or calculations.