Why does `a == b or c or d` always evaluate to True?

吃可爱长大的小学妹 提交于 2019-12-02 10:37:49
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.

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:

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

The or operator chooses the first argument with a positive truth value:

if ("Jon"):

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.

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. Use multiple == operators to explicitly check against each value:
    if name == "Kevin" or name == "Jon" or name == "Inbar":

  2. Compose a sequence of valid values, and use the in operator to test for membership:
    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

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.

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

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.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!