2013-11-15 5 views
69

무단 사용자에 대한 액세스를 거부하는 보안 시스템을 작성 중입니다.`a == b or c or d`가 항상 True로 평가되는 이유는 무엇입니까?

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을 시도했지만 그 결과는 같습니다.

+0

조건을 쓰는 데 사용되는 대부분의 관용어는 'if name in [Kevin ","Jon ","Inbar "] : – djinn

답변

103

많은 경우 파이썬은 자연스러운 영어처럼 보이고 작동하지만 추상화가 실패하는 경우입니다. 사람들은 컨텍스트 단서를 사용하여 "Jon"과 "Inbar"가 동사 "equals"에 조인 된 객체라고 판단 할 수 있지만 파이썬 인터프리터는 좀 더 문자 적입니다.

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

or 오퍼레이터 양성 truth value으로 첫번째 인수를 선택 :

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

는 논리적으로 동일하다 : 대한 사용자 밥,

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

어느 등가이다

if ("Jon"): 

"Jon"은 양수 값이므로, if 블록이 실행됩니다. 이것이 주어진 이름에 관계없이 "액세스 허용"이 인쇄되는 원인입니다.

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


이 조건을 올바르게 구성하는 데는 두 가지 일반적인 방법이 있습니다. 회원 테스트
if name == "Kevin" or name == "Jon" or name == "Inbar":

  • 유효 값들의 시퀀스를 작성하고, in 연산자를 사용 :

    1. 사용 여러 == 연산자 명시 각 값에 대하여 확인
      if name in ("Kevin", "Jon", "Inbar"):

    2 개 중 일반적으로 두 번째는 더 쉬워야합니다.

    In [1]: name = "Inbar" 
    
    In [2]: %timeit name == "Keven" or name == "Jon" or name == "Inbar" 
    10000000 loops, best of 3: 116 ns per loop 
    
    In [3]: %timeit name in ("Keven", "Jon", "Inbar") 
    10000000 loops, best of 3: 65.2 ns per loop