2012-09-30 26 views
108

Tôi đang thực hiện một phân tích cú pháp Python, và điều này là thực sự khó hiểu cho tôi:Tính tương đối của "in" trong Python?

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

chính xác như thế "trong" công việc trong Python, liên quan đến associativity, vv?

Tại sao hai biểu thức này không hoạt động giống nhau?

+6

Có thể bạn đang nhấn vào hành vi được mô tả ở đây: http://docs.python.org/reference/expressions.html#not-in, cái cho phép bạn viết 'if a millimoose

+3

@millimoose: Vâng, tôi chưa bao giờ nghĩ đến 'in' như một toán tử" so sánh "mà tôi đoán. : \ – Mehrdad

+0

Xin chào [Loại trình phân tích cú pháp nào được sử dụng trong trình thông dịch python?] (Http://stackoverflow.com/questions/15532616/what-type-of-parser-is-used-in-python-interpreter) –

Trả lời

123

1 in [] in 'a' được đánh giá là (1 in []) and ([] in 'a').

Vì điều kiện đầu tiên (1 in []) là False, toàn bộ điều kiện được đánh giá là False; ([] in 'a') không bao giờ thực sự được đánh giá, do đó không có lỗi nào được nêu ra.

Dưới đây là các định nghĩa tuyên bố:

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 Thật tuyệt vời, cảm ơn rất nhiều! Nó trông thực sự tiện dụng, nếu chỉ tôi biết về nó! Bạn có biết điều này nằm trong tài liệu này không? Tôi [xem] (http://docs.python.org/reference/expressions.html#boolean-operations) nhưng không thể tìm thấy bất cứ điều gì đề xuất điều này! – Mehrdad

+1

'false' có thể được sử dụng thay vì 'sai' ở đây. – jfs

+1

@ J.F.Sebastian cảm ơn, đã khắc phục điều đó. –

22

Python làm những điều đặc biệt với sự so sánh chuỗi.

Sau đây là những đánh giá khác nhau:

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" 

Trong cả hai trường hợp, mặc dù nếu so sánh đầu tiên là False, phần còn lại của báo cáo kết quả sẽ không được xem xét.

Đối với trường hợp cụ thể của bạn,

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' 

Ngoài ra để chứng minh sự cai trị đầu tiên ở trên, đây là những báo cáo rằng đánh giá là 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 

Precedence của nhà khai thác python: http://docs.python.org/reference/expressions.html#summary

11

From the documentation:

So sánh có thể được xích tùy tiện, ví dụ, x < y < = z tương đương với x < y và y < = z, ngoại trừ rằng y được đánh giá chỉ một lần (nhưng trong cả hai trường hợp z không được đánh giá ở tất cả khi x < y được tìm thấy là sai).

Điều này có nghĩa là không có sự kết hợp trong x in y in z!

Sau đây là tương đương:

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

Câu trả lời ngắn, kể từ khi con đường dài đã được trao nhiều lần ở đây và theo những cách tuyệt vời, đó là các biểu thức boolean là ngắn mạch, đây là có ngừng đánh giá khi một sự thay đổi của sự thật trong sai hoặc ngược lại không thể xảy ra bằng cách đánh giá thêm.

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

Nó có thể là một chút ngắn (không ý định chơi chữ) như là một câu trả lời, nhưng như đã nói, tất cả các giải thích khác là allready thực hiện khá tốt ở đây, nhưng tôi nghĩ rằng thuật ngữ xứng đáng được đề cập .

Các vấn đề liên quan