为什么`a == x或y或z`总是评估为True? [英] Why does `a == x or y or z` always evaluate to True?

查看:67
本文介绍了为什么`a == x或y或z`总是评估为True?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在编写一个拒绝对未授权用户进行访问的安全系统.

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.

为什么会这样?我已经明确指出,仅当 name 等于Kevin,Jon或Inbar时才授予访问权限.我也尝试了相反的逻辑,如果 Kevin.或乔恩"或"Inbar"==名称,但结果相同.

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.

注意:此问题旨在作为此非常常见问题的规范重复目标.还有一个流行的问题如何针对单个值测试多个变量具有相同的基本问题,但是比较目标相反.此问题不应作为该问题的重复部分而关闭,因为Python的新手可能会遇到此问题,他们可能难以将反问题中的知识应用于他们的问题.

Note: this question is intended as the canonical duplicate target of this very common problem. There is another popular question How to test multiple variables 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.

推荐答案

在许多情况下,Python的外观和行为类似于自然的英语,但这是这种抽象失败的一种情况.人们可以使用上下文线索来确定乔恩"事件.和"Inbar"是连接到动词"equals"的对象,但是Python解释器的含义更为文字化.

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.

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

在逻辑上等同于:

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

对于用户Bob,这等同于:

Which, for user Bob, is equivalent to:

if (False) or ("Jon") or ("Inbar"):

or 运算符选择具有正真实值:

if "Jon":

由于乔恩"具有一个正的真值,将执行 if 块.这就是导致访问授权"的原因.不管给出的名称如何都可以打印.

And since "Jon" has a positive truth value, the if block executes. That is what causes "Access granted" to be printed regardless of the name given.

如果"Kevin"为0,则所有这些推理也适用于表达式"".或乔恩"或"Inbar"==名称.第一个值"Kevin" 为true,因此执行 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 if block executes.

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

There are two common ways to properly construct this conditional.

  1. 使用多个 == 运算符来显式检查每个值:

  1. Use multiple == operators to explicitly check against each value:

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
    


    对于那些可能想证明如果a == b或c或d或e:... 确实如此的人.内置的 ast 模块提供了答案:


    For those who may want proof that if a == b or c or d or e: ... is indeed parsed like this. The built-in ast module provides an answer:

    >>> 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())]))
    

    正如人们所看到的,它是布尔运算符 or 应用于四个子表达式:比较 a == b ;和简单的表达式 c d e .

    As one can see, it's the boolean operator or applied to four sub-expressions: comparison a == b; and simple expressions c, d, and e.

    这篇关于为什么`a == x或y或z`总是评估为True?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆