当前位置: 首页 > 知识库问答 >
问题:

为什么"a==x或y或z"总是求值为True?

谭卜鹰
2023-03-14

我正在编写一个安全系统,拒绝未经授权的用户访问。

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.

为什么会发生这种情况?我已经明确声明,只有当name等于Kevin、Jon或Inbar时,才允许访问。我也尝试过相反的逻辑,如果“Kevin”或“Jon”或“Inbar”==name,但结果是一样的。

注意:这个问题旨在作为这个非常常见的问题的规范重复目标。还有另一个热门问题如何针对单个值测试多个变量?这有同样的基本问题,但比较目标是相反的。这个问题不应该作为那个问题的重复被关闭,因为这个问题是Python的新手遇到的,他们可能很难将反向问题中的知识应用到他们的问题中。

共有3个答案

姜俊逸
2023-03-14

简单的工程问题,让我们更进一步。

In [1]: a,b,c,d=1,2,3,4
In [2]: a==b
Out[2]: False

但是,继承自C语言的Python将非零整数的逻辑值计算为True。

In [11]: if 3:
    ...:     print ("yey")
    ...:
yey

现在,Python构建在该逻辑的基础上,并允许您使用逻辑文本,例如或整数,等等

In [9]: False or 3
Out[9]: 3

终于

In [4]: a==b or c or d
Out[4]: 3

正确的书写方式是:

In [13]: if a in (b,c,d):
    ...:     print('Access granted')

为了安全起见,我还建议你不要硬编码密码。

景唯
2023-03-14

如果name==“Kevin”或“Jon”或“Inbar”,则在中有3个条件检查:

  • name=="Kevin"
  • 乔恩
  • Inbar

这个if语句等价于

if name == "Kevin":
    print("Access granted.")
elif "Jon":
    print("Access granted.")
elif "Inbar":
    print("Access granted.")
else:
    print("Access denied.")

由于elif"Jon"将始终为真,因此授予任何用户访问权限

您可以使用下面的任何一种方法

快啊

if name in ["Kevin", "Jon", "Inbar"]:
    print("Access granted.")
else:
    print("Access denied.")

缓慢的

if name == "Kevin" or name == "Jon" or name == "Inbar":
    print("Access granted.")
else:
    print("Access denied.")

慢不必要的代码

if name == "Kevin":
    print("Access granted.")
elif name == "Jon":
    print("Access granted.")
elif name == "Inbar":
    print("Access granted.")
else:
    print("Access denied.")

锺离鸿
2023-03-14

在许多情况下,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"):

运算符选择具有正真值的第一个参数:

if "Jon":

由于Jon具有正真值,if块将执行。这就是为什么“授权访问”会被打印出来,而不管给出的名字是什么。

如果“Kevin”或“Jon”或“Inbar”==name,所有这些推理也适用于表达式。第一个值,“Kevin”,为true,因此执行if块。

有两种常见的方法可以正确构造此条件。

>

  • 使用多个==运算符显式检查每个值:

    if name == "Kevin" or name == "Jon" or name == "Inbar":
    

    组成一个有效值的集合(例如集合、列表或元组),并使用运算符中的测试成员资格:

    if name in {"Kevin", "Jon", "Inbar"}:
    

    一般而言,应优先选择第二种,因为它更容易阅读,也更快:

    >>> 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
    

    对于那些可能想要证明if a==b或c或d或e的人:...确实是这样解析的。内置的ast模块提供了一个答案:

    >>> import ast
    >>> ast.parse("a == b or c or d or e", "<string>", "eval")
    <ast.Expression object at 0x7f929c898220>
    >>> print(ast.dump(_, indent=4))
    Expression(
        body=BoolOp(
            op=Or(),
            values=[
                Compare(
                    left=Name(id='a', ctx=Load()),
                    ops=[
                        Eq()],
                    comparators=[
                        Name(id='b', ctx=Load())]),
                Name(id='c', ctx=Load()),
                Name(id='d', ctx=Load()),
                Name(id='e', ctx=Load())]))
    

    可以看到,它是应用于四个子表达式的布尔运算符:比较a==b;和简单表达式cde

  •  类似资料:
    • 问题内容: 我正在编写一个拒绝访问未授权用户的安全系统。 它可以按预期授予授权用户访问权限,但也允许未经授权的用户使用! 为什么会发生这种情况?我已经明确指出仅在name等于,或 时才授予访问权限。我也尝试过相反的逻辑if ,但是结果是一样的。 问题答案: 在许多情况下,Python的外观和行为都像自然的英语,但这是这种抽象失败的一种情况。人们可以使用上下文线索来确定和是与动词连接的对象,但是Py

    • 问题内容: 例如: 当不带参数调用时,上述函数将打印并返回 Python为什么要这样做?如何最好地利用这一功能? 问题答案: “ ”表达式对赋值的作用: 我们有时会在Python中看到这样的示例,以三元赋值代替条件表达式(实际上,这有助于启发该语言添加条件语句)。 如果返回,则分配值为 条件表达式的相同用例(即三元分配) 这是一个条件表达式的示例,该条件表达式可以完成相同的任务,但可能不那么神秘。

    • 我有以下功能: 此代码给出了

    • 这部分是学术性的,就我的目的而言,我只需要四舍五入到小数点后两位;但我很想知道发生了什么会产生两种略有不同的结果。 这是我编写的测试,将其缩小到最简单的实现: 但它失败了,输出如下: 有谁能详细解释一下是什么原因导致 我在一个答案中寻找的一些要点是:精度损失在哪里?哪种方法是首选的,为什么?哪一个实际上是正确的?(在纯数学中,不可能两者都是对的。也许两者都是错的?)对于这些算术运算,有没有更好的解

    • 我正在编写一个安全系统,拒绝未经授权的用户访问。 它按预期授予授权用户访问权限,但也允许未经授权的用户进入! 为什么会出现这种情况?我已经明确声明,只有当等于Kevin、Jon或inbar时才授予访问权限。我也尝试过相反的逻辑,,但结果是一样的。

    • 问题内容: 考虑以下示例: 我不确定Java语言规范中是否有一项规定要加载变量的先前值以便与右侧()进行比较,该变量应按照方括号内的顺序进行计算。 为什么第一个表达式求值,而第二个表达式求值?我本来希望先被评估,然后再与自身()比较并返回。 这个问题与Java表达式中子表达式的求值顺序不同,因为这里绝对不是“子表达式”。需要 加载 它以进行比较,而不是对其进行“评估”。这个问题是特定于Java的,