파이썬에서 왜“0, 0 == (0, 0)”이“(0, False)”와 같습니까?


118

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

두 접근 방식에서 결과가 다른 이유는 무엇입니까? 항등 연산자는 튜플을 다르게 처리합니까?

답변:


156

처음 두 표현식은 모두 튜플로 구문 분석됩니다.

  1. (0, 0) == 0( False), 뒤에0
  2. 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.


17
쉼표 연산자는 같음 보다 우선 순위 가 낮다고 말하고 싶습니다. 같음에 대한 평가가 쉼표 연산자보다 우선하기 때문입니다. 같음이 쉼표 연산자보다 우선합니다. 그러나 이것은 항상 혼란의 근원입니다. 다른 출처가 상황을 뒤집을 수 있음을 지적하고 싶었습니다.
tomsmeding

2
대신 ,더 덜 단단히 묶는 다고 말함으로써 더 낮거나 더 높은 말 혼동을 피할 수 있습니다 ==.
amalloy

4
쉼표는 연산자 가 아닙니다 . docs.python.org/3.4/faq/…
Chris_Rands

48
문서는 그들이 원하는 모든 것을 주장 할 수 있지만 그것은 중요하지 않습니다. 모든 연산자가 자체 생산을 가져오고 구현의 어디에도 명시적인 "우선 순위"가 없도록 구문 분석기를 작성할 수 있지만 이러한 구문 단위가 연산자가되는 것을 막지는 못합니다. 구현 특정 방식으로 "연산자"를 재정의 할 수 있습니다. , 분명히 그들이 파이썬에서 한 일이지만, 용어의 의미를 바꾸지는 않습니다. 쉼표는 사실상 튜플을 생성하는 연산자입니다. 예를 들어 연산자는 상대적 우선 순위가 괄호에 의해 영향을받는 방식을 보여줍니다.
Mark Reed

68

세 가지 인스턴스 모두에서 볼 수있는 것은 언어 의 문법 사양 과 소스 코드에서 발견 된 토큰을 구문 분석하여 구문 분석 트리를 생성하는 방법의 결과입니다.

이 저수준 코드를 살펴보면 내부에서 일어나는 일을 이해하는 데 도움이 될 것입니다. 이러한 파이썬 문을 가져 와서 바이트 코드로 변환 한 다음 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 .


20

문제를 설명하는 또 다른 방법 : 아마도 사전 리터럴에 익숙 할 것입니다.

{ "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

17

작업이 수행되는 순서에 두 개의 괄호를 추가하면 결과를 더 잘 이해할 수 있습니다.

# 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.


6

첫 번째에서 Python은 두 가지의 튜플을 만듭니다.

  1. 다음 (0, 0) == 0으로 평가 되는 표현식False
  2. 상수 0

두 번째는 반대입니다.


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)에 대해서만 수행됩니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.