2012-09-30 6 views
108

は、私はPythonのパーサを作ってるんだ、これは本当に私を混乱次のとおりです。Pythonの "in"の関連性は?

>>> 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で仕事「に」どのように正確に?

これらの式のうち2つの式が同じように動作しないのはなぜですか?

+6

http://docs.python.org/reference/expressions.html#not-inここに記載されている動作をする可能性があります。これは、 'a millimoose

+3

@millimoose:ええと、私は "比較"演算子として 'in'を考えなかった。 :\ – Mehrdad

+0

こんにちは[どのような種類のパーサーは、Pythonインタープリタで使用されますか?](http://stackoverflow.com/questions/15532616/what-type-of-parser-is-used-in-python-interpreter) –

答えて

123

1 in [] in 'a'は、(1 in []) and ([] in 'a')と評価されます。

第1条件(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   
+0

Whoa! ! +1それは素晴らしいです、ありがとう!それは私がそれについて知っていれば本当に便利ですね!これがドキュメントのどこにあるのか分かりますか?私は(見て)(http://docs.python.org/reference/expressions.html#boolean-operations)、これを示唆したものは何も見つかりませんでした! – Mehrdad

+1

ここでは「間違った」の代わりに「偽」を使用することができます。 – jfs

+1

@ J.F.Sebastianありがとう、それを修正しました。 –

22

Pythonは連鎖比較して特別なことを行います。

次が異なって評価されます。最初の比較がFalseであればいずれの場合も

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" 

しかし、文の残りの部分は見れません。上記の最初の規則性を実証するためにあなたの特定のケースについては

、また

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

From the documentation:

比較は任意に連鎖することができ、例えば、< Y < = Zは、x < YおよびY < = Zに相当し、xはただし、yは1回だけ評価されます(ただし、x <が偽であると判断された場合、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

短い答えと優れた方法で、これは持っている、ブール式が短絡であるということである。

は同等ですさらなる評価によって偽での真の変化が起こった場合、またはその逆の場合には評価を停止する。

http://en.wikipedia.org/wiki/Short-circuit_evaluationを参照)

それは答えとして(しゃれが意図していない)少し短いかもしれませんが、前述したように、他のすべての説明が出回っここに非常によく行われますが、私は用語が言及するに値すると思いました。