programing

"a == x 또는 y 또는 z"가 항상 참으로 평가되는 이유는 무엇입니까?"a"를 그 모든 것들과 어떻게 비교할 수 있습니까?

oldcodes 2023. 7. 8. 11:09
반응형

"a == x 또는 y 또는 z"가 항상 참으로 평가되는 이유는 무엇입니까?"a"를 그 모든 것들과 어떻게 비교할 수 있습니까?

저는 무단 사용자의 접근을 거부하는 보안 시스템을 작성하고 있습니다.

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케빈, 존 또는 인바와 같습니다. 논리인 반논시봤도지만해리를대저도,▁the,▁logic▁opposite▁tried▁i만지봤▁also,if "Kevin" or "Jon" or "Inbar" == name하지만 결과는 같습니다.


이 질문은 매우 일반적인 문제의 표준 중복 대상으로 사용됩니다.단일 값에 대한 동일성을 위해 여러 변수를 검정하는 방법에 대한 또 다른 일반적인 질문이 있습니다.동일한 근본적인 문제가 있지만 비교 대상은 반대입니다.이 문제는 Python에 새로 온 사람들이 반대 질문의 지식을 문제에 적용하는 데 어려움을 겪을 수 있기 때문에 이 질문의 중복으로 닫아서는 안 됩니다.

위해서in==솔루션은 다음과 같습니다.목록에서 여러 값의 구성원을 테스트하는 방법

대부분의 경우 Python은 자연스러운 영어처럼 보이고 행동하지만, 이것은 추상화가 실패하는 한 가지 경우입니다.사람들은 문맥 단서를 사용하여 "Jon"과 "Inbar"가 동사 "equals"에 연결된 객체라고 판단할 수 있지만, 파이썬 해석기는 더 문자 그대로입니다.

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

논리적으로 다음과 같습니다.

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

사용자 Bob의 경우 다음과 같습니다.

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

or연산자는 첫 번째 피연산자인 "참"을 선택합니다. 즉, 조건(또는 조건 중 "참"이 없는 경우 마지막 피연산자)을 만족시킵니다.

if "Jon":

이 진실이기 에, "이진" 때문에기존실이,때에,if블록이 실행됩니다.따라서 주어진 이름에 관계없이 "권한 부여"가 인쇄됩니다.

은 이든모추표현적도용다니됩에은론ion▁express다적니용▁all됩라는 표현에도 적용됩니다.if "Kevin" or "Jon" or "Inbar" == name 번째 값인 첫 번 째 값 값 ,"Kevin"사실입니다, 그래서.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

증거를 원하는 사람들을 위해.if a == b or c or d or 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())]))

연산자인 보시피, 그부연산니다입니다.or4개의 하위 개념에 됨: 네 개 하 개 에 용 적 비 : 교a == b 간단한 표현인 그고간단한표현들리표들▁and.c,d,그리고.e.

기존의 모든 답변 요약

(그리고 내 요점 몇 가지 추가)

설명:

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

논리적으로 다음과 같습니다.

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

사용자 Bob의 경우 다음과 같습니다.

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

을 참: Python 이 0 아 정 수 의 논 적 값 고 평 같 가 합 니 이 다 과 다 음 을 리 닌 은 ▁the ▁note 니 ▁as 참 합 고 다 ▁non ▁python ▁of ▁integer : ▁0 ▁valueTrue string 평가 하며 따서비있않리, 세트문열, 자등평다니반됩환수가를 반환합니다.True

or연산자는 양의 참 값을 가진 첫 번째 인수를 선택합니다.

따라서 "John"은 양의 진실 값을 가지며 if 블록이 실행됩니다. 왜냐하면 이제 다음과 같기 때문입니다.

if (False) or (True) or (True):

따라서 이름 입력에 관계없이 "권한 부여"가 인쇄됩니다.

솔루션:

솔루션 1: 다중 사용==는 각 값에 대해 합니다.

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

솔루션 2: 유효한 값 모음(예: 집합, 목록 또는 튜플)을 구성하고 다음을 사용합니다.in구성원 자격을 테스트할 연산자(예: 선호 방법)

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

OR

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

솔루션 3: 기본(효율적이지 않음)사용 if-elif-else

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

3지있다습에 3가지 상태 .if name == "Kevin" or "Jon" or "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.")

비어 있지 않은 목록, 집합, 문자열 등을 평가할 수 있으므로 True를 반환합니다.

따라서 다음과 같이 말할 때:

a = "Raul"
if a == "Kevin" or "John" or "Inbar":
    pass

당신은 실제로 다음과 같이 말하고 있습니다.

if "Raul" == "Kevin" or "John" != "" or "Inbar" != "":
    pass

"John" 및 "Inbar" 중 적어도 하나는 빈 문자열이 아니므로 전체 식은 항상 True를 반환합니다!

해결책:

a = "Raul"
if a == "Kevin" or a == "John" or a == "Inbar":
    pass

또는:

a = "Raul"
if a in {"Kevin", "John", "Inbar"}:
    pass

단순한 공학적 문제입니다. 간단히 좀 더 얘기해보죠.

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

마침내.

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

이 문서를 작성하는 올바른 방법은 다음과 같습니다.

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

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

용사를 합니다.match/case3. 이상

Python 3.10은 언어에 새로운 구문을 추가합니다.공식적으로 "구조 패턴 매칭"이라고 설명하지만, 대부분의 사람들은 구문에 따라 이를 부릅니다."match/case".

우리는 이 특별한 구문을 질문과 같은 예로 사용할 수 있습니다. 허용된 모든 사용자 이름과 일치하는 하나의 "대소문자"를 만들고 "와일드카드" 대소문자를 사용합니다._신에를 else따라서:

name = input("Hello. Please enter your name: ")
match name:
    case "Kevin" | "Jon" | "Inbar":
        print("Access granted.")
    case _:
        print("Access denied.")

는 결사다사여용 "합됩는"를 사용하여 .|,것은 아니다.or이것은 특별한 구문입니다: Python은 계산을 시도하지 않습니다."Kevin" | "Jon" | "Inbar"첫 번째(|문자열로 작동하지 않음) 대신 전체 을 다르게 해석합니다.case.

게다가 이미 언급된 바다코끼리 운영자에게 좀 더 드문 유용한 사례들도 있습니다.이것은 또한 유용한 사례가 되는 경향이 있습니다.

def calc_value():
    return 43

if (v := calc_value()) == 43 and v > 42:
    print('happy short, efficient and readable code')

의 각 부분이 개별적으로 읽기 때문에 작동합니다.그렇게(v := calc_value())이 실되고할니다됩에 됩니다.v첫 번째가 실패해도 네임스페이스에 다른 조건이나 계산을 위한 v가 남아 있습니다.

접근법

데이터 과학자가 이 문제에 접근하는 방법

가장 간단한 방법은 비교 연산자의 필요성을 없애고 목록을 사용하는 것입니다.ORM에 액세스하는 방법을 배우기 때문에 보안 시스템에서 이 기능이 인상적으로 보입니다.

user = input("Enter name: ")

if user in {"Bob", "Kevin", "Joe"}:
   print("Access granted, " + str(user) + ".")
else:
   print("Access denied.")

또는 위의 코드와 동일한 코드를 사용할 수 있습니다. 등록된 사용자 목록을 자신의 목록에 입력하기만 하면 됩니다.

user = input("Enter name: ")
users = {"Bob", "Kevin", "Joe", "a million more users if you like"}

if user in users:
   print("Access granted, " + str(user) + ".")
else:
   print("Access denied.")

공격 위험 없이 이 프로토콜을 안전하게 완료하려면 이중 매개 변수를 설정합니다.에 ORM이 할 수 있습니다.first그리고.last 및 "이름" 필드password또는secret question 사용자 증명을 할 수 . 해시 없이 사용자 자격 증명을 효율적으로 로드하려면 개체를 다음과 같이 정렬할 수 있습니다.

def lazy(i):
   j = 0 # For example
   while j < i:
      yield j
      j += 1

루프는 시스템의 시간과 에너지를 절약하기 위해 산출된 값만 소비합니다.

그런 다음 반복 목록을 사용하여 다음 작업을 수행할 수 있습니다.

for j in lazy_range(10):
   do_something_here(j)

이 문제는 메모리 관리, 보안 또는 단순히 유기 목록 또는 패키지화된 ORM을 통해 접근할 수 있습니다.

언급URL : https://stackoverflow.com/questions/20002503/why-does-a-x-or-y-or-z-always-evaluate-to-true-how-can-i-compare-a-to-al

반응형