"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
블록이 실행됩니다.
이 조건부를 올바르게 구성하는 두 가지 일반적인 방법이 있습니다.
개의
==
값에 명시적으로 : " " " 값 에 으 " 는 " 하 " 산 " 자 " 연 " 각 "if name == "Kevin" or name == "Jon" or name == "Inbar":
집합(, , 튜플)을 하고 " " " " " " " " " " ( " " " " " " " " " " ( " " " " " " " " " " " " " " " " " " 를 합니다.
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())]))
연산자인 보시피, 그부연산니다입니다.or
4개의 하위 개념에 됨: 네 개 하 개 에 용 적 비 : 교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
/case
3. 이상
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
'programing' 카테고리의 다른 글
SQL: 방금 삽입한 값의 ID를 가져오는 방법은 무엇입니까? (0) | 2023.07.08 |
---|---|
고유 ID 생성 (0) | 2023.07.08 |
현재 시간을 날짜 시간으로 가져오는 방법 (0) | 2023.07.08 |
vue.jest unit - 계산된 값을 기반으로 Watcher를 테스트하는 방법? (setComputed는 더 이상 사용되지 않습니다.) (0) | 2023.07.08 |
매개 변수 전달을 통한 추가Target:action:ControlEvents (0) | 2023.07.08 |