2015-07-15 52 views
449

Nếu tôi làm điều này:Tại sao "không (True) trong [False, True]" return False?

>>> False in [False, True] 
True 

Đó trả True. Đơn giản chỉ vì False nằm trong danh sách.

Nhưng nếu tôi làm:

>>> not(True) in [False, True] 
False 

Đó trả False. Trong khi not(True) bằng False:

>>> not(True) 
False 

Tại sao?

+0

http://stackoverflow.com/questions/31354429/why-is-true-is-false-false-false-in-python/31354514#31354514 – Kasramvd

Trả lời

697

điều hành ưu tiên2.x, 3.x. Mức độ ưu tiên của not thấp hơn giá trị của in. Vì vậy, nó tương đương với:

>>> not (True in [False, True]) 
False 

Đây là những gì bạn muốn:

>>> (not True) in [False, True] 
True 

Như @Ben chỉ ra: Chúng tôi khuyên bạn không bao giờ viết not(True), thích not True. Cái trước đây làm cho nó trông giống như một cuộc gọi hàm, trong khi not là một toán tử, không phải là một hàm.

+267

@ Texom512: Tôi cũng khuyên bạn không nên viết 'không (Đúng) '; thích 'không đúng'. Việc đầu tiên làm cho nó trông giống như một cuộc gọi chức năng, đó là nơi mà sự nhầm lẫn của bạn đến từ; nếu 'not' là một hàm, thì' không (True) trong ... 'không thể là' không ((True) trong ...) '. Bạn phải biết đó là một toán tử (hoặc bạn kết thúc trong các tình huống như thế này), vì vậy bạn nên viết nó như một toán tử, không che giấu nó như một hàm. – Ben

+7

Ngoài ra, nếu bạn định sử dụng khoảng cách để cho biết ưu tiên vì lợi ích của người đọc, trước tiên hãy đảm bảo bạn đã đúng. Có thể OK để viết 'a + b * c + d', sẽ rất tệ khi viết' a + b * c + d'. Vì vậy, 'không (True)' là xấu bởi biện pháp đó quá. –

+18

Thực ra, ** không bao giờ ** viết 'không đúng'. Thay vào đó hãy viết 'False'. – Darkhogg

35

Ưu tiên toán tử. in liên kết chặt chẽ hơn not, do đó, biểu thức của bạn tương đương với not((True) in [False, True]).

33

Đó là tất cả về operator precedence (in mạnh hơn not). Nhưng nó có thể dễ dàng khắc phục bằng cách thêm dấu ngoặc đơn ở đúng nơi:

(not(True)) in [False, True] # prints true 

viết:

not(True) in [False, True] 

là giống như:

not((True) in [False, True]) 

trông nếu True có trong danh sách và trả về "không" của kết quả.

14

Nó được đánh giá như not True in [False, True], mà trả về FalseTrue là trong [False, True]

Nếu bạn cố gắng

>>>(not(True)) in [False, True] 
True 

Bạn nhận được các kết quả mong đợi.

71

not x in y được đánh giá là x not in y

Bạn có thể thấy chính xác những gì đang xảy ra bởi tháo mã.các công trình trường hợp đầu tiên như bạn mong đợi:

>>> x = lambda: False in [False, True] 
>>> dis.dis(x) 
    1   0 LOAD_GLOBAL    0 (False) 
       3 LOAD_GLOBAL    0 (False) 
       6 LOAD_GLOBAL    1 (True) 
       9 BUILD_LIST    2 
      12 COMPARE_OP    6 (in) 
      15 RETURN_VALUE 

Trường hợp thứ hai, đánh giá để True not in [False, True], đó là False rõ:

>>> x = lambda: not(True) in [False, True] 
>>> dis.dis(x) 
    1   0 LOAD_GLOBAL    0 (True) 
       3 LOAD_GLOBAL    1 (False) 
       6 LOAD_GLOBAL    0 (True) 
       9 BUILD_LIST    2 
      12 COMPARE_OP    7 (not in) 
      15 RETURN_VALUE   
>>> 

Những gì bạn muốn bày tỏ thay vì là (not(True)) in [False, True], mà như mong đợi là True, và bạn có thể thấy lý do:

>>> x = lambda: (not(True)) in [False, True] 
>>> dis.dis(x) 
    1   0 LOAD_GLOBAL    0 (True) 
       3 UNARY_NOT   
       4 LOAD_GLOBAL    1 (False) 
       7 LOAD_GLOBAL    0 (True) 
      10 BUILD_LIST    2 
      13 COMPARE_OP    6 (in) 
      16 RETURN_VALUE   
+12

Luôn luôn có một chàng trai với 'dis' nhưng đây là một câu trả lời rất có giá trị vì nó cho thấy rằng thực sự' không in' được sử dụng – jamylak

+21

Bytecode là một chi tiết thực hiện của trình thông dịch CPython. Đây là một câu trả lời CPython cho một câu hỏi Python, trên thực tế nó có thể được trả lời tốt hơn từ các tài liệu tham khảo ngôn ngữ trực tiếp. – wim

+4

@wim Tôi sẽ cho rằng việc thực hiện bytecode không quan trọng như việc tháo gỡ thực tế. Triển khai khác được đảm bảo để tạo ra một cái gì đó chức năng giống hệt nhau, do đó, hiểu một trong những tháo gỡ cung cấp đủ cái nhìn sâu sắc để hiểu được "tại sao" và không phải là lowlevel "như thế nào". –

6

Hãy xem nó như một hoạt động kiểm tra ngăn chặn bộ sưu tập: [False, True] là danh sách chứa một số phần tử.

Biểu thức True in [False, True] trả về True, như True là một phần tử có trong danh sách.

Do đó, not True in [False, True] cung cấp cho các "boolean ngược lại", not kết quả của biểu thức trên (không có bất kỳ dấu ngoặc đơn để duy trì ưu tiên, như in có độ ưu tiên lớn hơn not điều hành). Do đó, not True sẽ cho kết quả False.

Mặt khác, (not True) in [False, True], bằng False in [False, True], là True (False được chứa trong danh sách).

13

Cùng với câu trả lời khác mà đề cập đến ưu tiên của not thấp hơn in, thực sự tuyên bố của bạn là tương đương với:

not (True in [False, True]) 

Nhưng lưu ý rằng nếu bạn không tách rời tình trạng của bạn từ những người khác, trăn sẽ sử dụng 2 vai trò (precedence hoặc chaining) để tách biệt, và trong trường hợp này python được ưu tiên sử dụng. Ngoài ra, lưu ý rằng nếu bạn muốn tách riêng một điều kiện bạn cần phải đặt tất cả các điều kiện trong ngoặc đơn không chỉ là đối tượng hoặc giá trị:

(not True) in [False, True] 

Nhưng như đã đề cập, có một sửa đổi bởi python trên các nhà khai thác mà được chaining:

Dựa trên python documentation:

Lưu ý rằng so sánh, kiểm tra thành viên, và kiểm tra danh tính, một sẽ có cùng quyền ưu tiên và có một tính năng chaining từ trái sang phải như được mô tả trong phần So sánh.

Ví dụ kết quả của sau tuyên bố là False:

>>> True == False in [False, True] 
False 

Bởi vì trăn chí chuỗi những điều khoản như sau:

(True == False) and (False in [False, True]) 

Mà chính xác là False and True đó là False.

Bạn có thể giả định rằng đối tượng trung tâm sẽ được chia sẻ giữa 2 thao tác và các đối tượng khác (Sai ​​trong trường hợp này).

Và lưu ý rằng nó cũng đúng đối với tất cả các so sánh, trong đó có các bài kiểm tra thành viên và các hoạt động kiểm tra danh tính mà là toán hạng sau:

in, not in, is, is not, <, <=, >, >=, !=, == 

Ví dụ:

>>> 1 in [1,2] == True 
False 

Một ví dụ nổi tiếng là dãy số:

7<x<20 

bằng:

7<x and x<20 
6

Để làm rõ về một số câu trả lời khác, thêm dấu ngoặc đơn sau một toán tử đơn hạng không thay đổi độ ưu tiên của nó. not(True) không làm cho not liên kết chặt chẽ hơn với True. Nó chỉ là một bộ ngoặc đơn dư thừa xung quanh True. Nó giống như (True) in [True, False]. Các dấu ngoặc đơn không làm gì cả. Nếu bạn muốn ràng buộc chặt chẽ hơn, bạn phải đặt dấu ngoặc đơn xung quanh toàn bộ biểu thức, nghĩa là cả toán tử và toán hạng, tức là, (not True) in [True, False].

Để thấy điều này một cách khác, hãy xem xét

>>> -2**2 
-4 

** liên kết chặt chẽ hơn -, đó là lý do tại sao bạn có được những tiêu cực của hai bình phương, chứ không phải vuông âm hai (đó sẽ là tích cực bốn).

Điều gì sẽ xảy ra nếu bạn muốn hình vuông hai âm? Rõ ràng, bạn muốn thêm dấu ngoặc đơn:

>>> (-2)**2 
4 

Tuy nhiên, nó không phải là hợp lý để mong đợi những điều sau để cung cấp cho 4

>>> -(2)**2 
-4 

-(2) cũng giống như -2. Các dấu ngoặc đơn hoàn toàn không có gì. not(True) hoàn toàn giống nhau.

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