`a == b 또는 c 또는 d`가 항상 True로 평가되는 이유

python boolean boolean-expression


무단 사용자에 대한 액세스를 거부하는 보안 시스템을 작성 중입니다.

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.")

예상대로 권한이 부여 된 사용자에게 액세스 권한을 부여하지만 권한이없는 사용자도 허용합니다!

Hello. Please enter your name:
Bob
Access granted.

왜 이런 일이 발생합니까? name 이 Kevin, Jon 또는 Inbar와 같은 경우에만 액세스 권한을 부여한다고 명시했습니다 . if "Kevin" or "Jon" or "Inbar" == name 인 경우 반대 논리를 시도 했지만 결과는 동일합니다.




Answer 1 Kevin


많은 경우, 파이썬은 자연 영어처럼 보이고 행동하지만, 추상화가 실패하는 경우입니다. 사람들은 문맥 단서를 사용하여 "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"):

or 운영자는 포지티브 첫번째 인수 선택 진리 값 :

if ("Jon"):

그리고 "Jon"은 양의 진리 값을 가지므로 if 블록이 실행됩니다. 이것이 이름에 관계없이 "액세스 허용"이 인쇄되는 이유입니다.

if "Kevin" or "Jon" or "Inbar" == name 인 경우이 모든 추론이 표현식에도 적용됩니다 . 첫 번째 값 "Kevin" 은 true이므로 if 블록이 실행됩니다.


이 조건을 올바르게 구성하는 데는 두 가지 일반적인 방법이 있습니다.

  1. 여러 == 연산자를 사용 하여 각 값을 명시 적으로 확인하십시오.
    if name == "Kevin" or name == "Jon" or name == "Inbar":

  2. 유효한 값 시퀀스를 작성하고 in 연산자를 사용하여 멤버십을 테스트하십시오.
    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



Answer 2 user1854182


간단한 엔지니어링 문제입니다. 간단히 설명하겠습니다.

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

그러나 C 언어에서 상속 된 Python은 0이 아닌 정수의 논리 값을 True로 평가합니다.

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

이제 파이썬은 그 논리를 기반으로하고 정수와 같은 논리 리터럴을 사용할 수 있습니다.

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

Finally

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

그것을 쓰는 올바른 방법은 다음과 같습니다.

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

안전을 위해 암호를 하드 코딩하지 않는 것이 좋습니다.