파이썬에서 "in"의 연관성?


107

저는 파이썬 파서를 만들고 있는데 이것은 정말 혼란 스럽습니다.

>>>  1 in  []  in 'a'
False

>>> (1 in  []) in 'a'
TypeError: 'in <string>' requires string as left operand, not bool

>>>  1 in ([] in 'a')
TypeError: 'in <string>' requires string as left operand, not list

연관성 등과 관련하여 Python에서 "in"이 정확히 어떻게 작동합니까?

이 두 표현이 같은 방식으로 작동하지 않는 이유는 무엇입니까?


6
: 당신은 아마 행동이 여기에 설명 된 타격하고 docs.python.org/reference/expressions.html#not-in을 , 당신이 쓰는 할 수있는 하나 if a < b < c:하고 직관적으로 작업이
millimoose

3
@millimoose : 예, 저는 in"비교"연산자로 생각한 적이 없습니다 . : \
user541686

답변:


123

1 in [] in 'a'로 평가됩니다 (1 in []) and ([] in 'a').

첫 번째 조건 ( 1 in [])이 False이므로 전체 조건은 다음과 같이 평가됩니다 False. ([] in 'a')실제로 평가되지 않으므로 오류가 발생하지 않습니다.

다음은 명령문 정의입니다.

In [121]: def func():
   .....:     return 1 in [] in 'a'
   .....: 

In [122]: dis.dis(func)
  2           0 LOAD_CONST               1 (1)
              3 BUILD_LIST               0
              6 DUP_TOP             
              7 ROT_THREE           
              8 COMPARE_OP               6 (in)
             11 JUMP_IF_FALSE            8 (to 22)  #if first comparison is wrong 
                                                    #then jump to 22, 
             14 POP_TOP             
             15 LOAD_CONST               2 ('a')
             18 COMPARE_OP               6 (in)     #this is never executed, so no Error
             21 RETURN_VALUE         
        >>   22 ROT_TWO             
             23 POP_TOP             
             24 RETURN_VALUE        

In [150]: def func1():
   .....:     return (1 in  []) in 'a'
   .....: 

In [151]: dis.dis(func1)
  2           0 LOAD_CONST               1 (1)
              3 LOAD_CONST               3 (())
              6 COMPARE_OP               6 (in)   # perform 1 in []
              9 LOAD_CONST               2 ('a')  # now load 'a'
             12 COMPARE_OP               6 (in)   # compare result of (1 in []) with 'a'
                                                  # throws Error coz (False in 'a') is
                                                  # TypeError
             15 RETURN_VALUE   



In [153]: def func2():
   .....:     return 1 in ([] in 'a')
   .....: 

In [154]: dis.dis(func2)
  2           0 LOAD_CONST               1 (1)
              3 BUILD_LIST               0
              6 LOAD_CONST               2 ('a') 
              9 COMPARE_OP               6 (in)  # perform ([] in 'a'), which is 
                                                 # Incorrect, so it throws TypeError
             12 COMPARE_OP               6 (in)  # if no Error then 
                                                 # compare 1 with the result of ([] in 'a')
             15 RETURN_VALUE        

우와 !! +1 놀랍습니다. 정말 감사합니다! 내가 그것에 대해 알고 있다면 정말 편리해 보입니다! 문서에서 이것이 어디에 있는지 알고 있습니까? 나는 보았지만 이것을 제안하는 것을 찾을 수 없었습니다!
user541686

1
참고 : []거짓이지만, []아니다 False, 예를 들어 [] and anything반환 [](하지 False).
jfs

6
@Mehrdad 이 출력을 생성하기 위해 iPython 과 함께 사용 된 Python 디스어셈블러 를 확인하십시오 .
Jeff Ferland

파이썬의 어떤 버전이 이것을 생성했는지는 모르지만, 파이썬 3.2는 분명히 새로운 바이트 코드를 가지고 있습니다 : JUMP_IF_FALSE_OR_POP, 이것은 시퀀스를 13에서 12로 한 명령만큼 단축시킵니다. 멋진 대답-감사합니다 !!
Dave

@ 데이브 그것은의 파이썬 2.6.6 (iPython)
애쉬 위니 Chaudhary

22

파이썬은 연결 비교로 특별한 일을합니다.

다음은 다르게 평가됩니다.

x > y > z   # in this case, if x > y evaluates to true, then
            # the value of y is being used to compare, again,
            # to z

(x > y) > z # the parenth form, on the other hand, will first
            # evaluate x > y. And, compare the evaluated result
            # with z, which can be "True > z" or "False > z"

두 경우 모두 첫 번째 비교가 False 이면 나머지 문은 확인되지 않습니다.

특정 경우에

1 in [] in 'a'   # this is false because 1 is not in []

(1 in []) in a   # this gives an error because we are
                 # essentially doing this: False in 'a'

1 in ([] in 'a') # this fails because you cannot do
                 # [] in 'a'

또한 위의 첫 번째 규칙을 보여주기 위해 True로 평가되는 문입니다.

1 in [1,2] in [4,[1,2]] # But "1 in [4,[1,2]]" is False

2 < 4 > 1               # and note "2 < 1" is also not true

Python 연산자 우선 순위 : http://docs.python.org/reference/expressions.html#summary


11

문서에서 :

비교는 임의로 연결될 수 있습니다. 예를 들어 x <y <= z는 y가 한 번만 평가된다는 점을 제외하고 x <y <= z와 동일합니다 (그러나 두 경우 모두 x <y가 발견되면 z는 전혀 평가되지 않습니다. 거짓).

이것이 의미하는 것은 x in y in z!에 연관성이 없다는 것입니다 .

다음은 동일합니다.

1 in  []  in 'a'
# <=>
middle = []
#            False          not evaluated
result = (1 in middle) and (middle in 'a')


(1 in  []) in 'a'
# <=>
lhs = (1 in []) # False
result = lhs in 'a' # False in 'a' - TypeError


1 in  ([] in 'a')
# <=>
rhs = ([] in 'a') # TypeError
result = 1 in rhs

3

짧은 대답은 긴 것이 이미 여러 번 주어 졌기 때문에 부울 표현식이 단락 되었다는 것입니다. 이것은 추가 평가에서 true 또는 그 반대로 변경 될 수없는 경우 평가를 중지 한 것입니다.

( http://en.wikipedia.org/wiki/Short-circuit_evaluation 참조 )

대답으로 약간 짧을 수도 있지만 (말장난이 아님) 언급했듯이 다른 모든 설명은 모두 여기에서 잘 수행되었지만 그 용어를 언급 할 가치가 있다고 생각했습니다.

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