Python에서 (Python 3.6으로 만 확인했지만 이전 버전의 많은 경우에도 유지되어야한다고 생각합니다) :
(0, 0) == 0, 0 # results in a two element tuple: (False, 0)
0, 0 == (0, 0) # results in a two element tuple: (0, False)
(0, 0) == (0, 0) # results in a boolean True
그러나:
a = 0, 0
b = (0, 0)
a == b # results in a boolean True
두 접근 방식에서 결과가 다른 이유는 무엇입니까? 항등 연산자는 튜플을 다르게 처리합니까?
답변
처음 두 표현식은 모두 튜플로 구문 분석됩니다.
(0, 0) == 0
(False
), 뒤에0
0
,0 == (0, 0)
(여전히False
그 정도입니다).
등식 연산자에 비해 쉼표 구분 기호의 상대적 우선 순위 때문에식이 그렇게 분할됩니다. 파이썬은 두 개의 식을 포함하는 튜플을 봅니다. 그 중 하나는 두 튜플 사이의 등식 테스트 대신 동등성 테스트입니다.
그러나 두 번째 문 집합 에서는 튜플이 될 a = 0, 0
수 없습니다 . 튜플은 값의 모음이며 동등성 테스트와 달리 Python에서는 할당에 값이 없습니다. 할당은 표현식이 아니라 명령문입니다. 튜플이나 기타 주변 식에 포함될 수있는 값이 없습니다. (a = 0), 0
튜플으로 해석을 강제하기 위해 같은 것을 시도 하면 구문 오류가 발생합니다. 그것은 튜플을 변수에 할당하는 것을 남깁니다. – 그것을 작성함으로써 더 명확하게 만들 수 있습니다 a = (0, 0)
– a = 0, 0
.
그래서 심지어 할당에 괄호없이에 a
,이 두 b
값을 할당받을은 (0,0)
, 그래서 a == b
그러므로 True
.
답변
세 가지 인스턴스 모두에서 볼 수있는 것은 언어 의 문법 사양 과 소스 코드에서 발견 된 토큰을 구문 분석하여 구문 분석 트리를 생성하는 방법의 결과입니다.
이 저수준 코드를 살펴보면 내부에서 일어나는 일을 이해하는 데 도움이 될 것입니다. 이러한 파이썬 문을 가져 와서 바이트 코드로 변환 한 다음 dis
모듈을 사용하여 디 컴파일 할 수 있습니다 .
사례 1 : (0, 0) == 0, 0
>>> dis.dis(compile("(0, 0) == 0, 0", '', 'exec'))
1 0 LOAD_CONST 2 ((0, 0))
3 LOAD_CONST 0 (0)
6 COMPARE_OP 2 (==)
9 LOAD_CONST 0 (0)
12 BUILD_TUPLE 2
15 POP_TOP
16 LOAD_CONST 1 (None)
19 RETURN_VALUE
(0, 0)
먼저 first와 비교 0
되고 False
. 그런 다음 튜플이이 결과와 마지막 0
으로 생성되므로 (False, 0)
.
사례 2 : 0, 0 == (0, 0)
>>> dis.dis(compile("0, 0 == (0, 0)", '', 'exec'))
1 0 LOAD_CONST 0 (0)
3 LOAD_CONST 0 (0)
6 LOAD_CONST 2 ((0, 0))
9 COMPARE_OP 2 (==)
12 BUILD_TUPLE 2
15 POP_TOP
16 LOAD_CONST 1 (None)
19 RETURN_VALUE
튜플은 0
첫 번째 요소로 구성됩니다. 두 번째 요소의 경우 첫 번째 경우와 동일한 검사가 수행되고으로 평가 False
되므로 (0, False)
.
사례 3 : (0, 0) == (0, 0)
>>> dis.dis(compile("(0, 0) == (0, 0)", '', 'exec'))
1 0 LOAD_CONST 2 ((0, 0))
3 LOAD_CONST 3 ((0, 0))
6 COMPARE_OP 2 (==)
9 POP_TOP
10 LOAD_CONST 1 (None)
13 RETURN_VALUE
여기서 보시 (0, 0)
다시피 두 튜플을 비교 하고True
.
답변
문제를 설명하는 또 다른 방법 : 아마도 사전 리터럴에 익숙 할 것입니다.
{ "a": 1, "b": 2, "c": 3 }
및 배열 리터럴
[ "a", "b", "c" ]
및 튜플 리터럴
( 1, 2, 3 )
그러나 당신이 깨닫지 못하는 것은 사전 및 배열 리터럴과 달리 튜플 리터럴 주위에 일반적으로 보는 괄호 가 리터럴 구문의 일부 가 아니라는 것 입니다. 튜플의 리터럴 구문은 쉼표로 구분 된 일련의 표현식입니다.
1, 2, 3
( Python 용 공식 문법 언어의 “exprlist” ).
이제 배열 리터럴은 무엇을 기대합니까?
[ 0, 0 == (0, 0) ]
평가하기 위해? 아마 다음과 같아야 할 것 같습니다.
[ 0, (0 == (0, 0)) ]
물론 [0, False]
. 마찬가지로 명시 적으로 괄호로 묶인 튜플 리터럴
( 0, 0 == (0, 0) )
를 얻는 것은 놀라운 일이 아닙니다 (0, False)
. 그러나 괄호는 선택 사항입니다.
0, 0 == (0, 0)
같은 것입니다. 그리고 그것이 당신이 얻는 이유 (0, False)
입니다.
튜플 리터럴을 둘러싼 괄호가 왜 선택적 인지 궁금하다면 , 구조 해제 할당을 그런 식으로 작성해야하는 것이 짜증나 기 때문입니다.
(a, b) = (c, d) # meh
a, b = c, d # better
답변
작업이 수행되는 순서에 두 개의 괄호를 추가하면 결과를 더 잘 이해할 수 있습니다.
# Build two element tuple comprising of
# (0, 0) == 0 result and 0
>>> ((0, 0) == 0), 0
(False, 0)
# Build two element tuple comprising of
# 0 and result of (0, 0) == 0
>>> 0, (0 == (0, 0))
(0, False)
# Create two tuples with elements (0, 0)
# and compare them
>>> (0, 0) == (0, 0)
True
쉼표는 표현식 을 구분하는 데 사용됩니다 (물론 괄호를 사용하여 다른 동작을 강제 할 수 있습니다). 나열된 스 니펫을 볼 때 쉼표로 ,
구분하고 평가할 표현식을 정의합니다.
(0, 0) == 0 , 0
#-----------|------
expr 1 expr2
튜플 (0, 0)
도 비슷한 방식으로 나눌 수 있습니다. 쉼표는 리터럴로 구성된 두 개의 표현식을 구분합니다 0
.
답변
첫 번째에서 Python은 두 가지의 튜플을 만듭니다.
- 다음
(0, 0) == 0
으로 평가 되는 표현식False
- 상수
0
두 번째는 반대입니다.
답변
이 예를보십시오 :
r = [1,0,1,0,1,1,0,0,0,1]
print(r==0,0,r,1,0)
print(r==r,0,1,0,1,0)
결과 :
False 0 [1, 0, 1, 0, 1, 1, 0, 0, 0, 1] 1 0
True 0 1 0 1 0
그런 다음 비교는 예제의 첫 번째 숫자 (0 및 r)에 대해서만 수행됩니다.