Tại sao không phải là (Đúng) trong [Sai, Đúng].


483

Nếu tôi làm điều này:

>>> False in [False, True]
True

Điều đó trả lại True . Đơn giản bởi vìFalse nằm trong danh sách.

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

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

Điều đó trở lại False. Trong khi đó not(True)bằng False:

>>> not(True)
False

Tại sao?



2
dấu ngoặc đơn của bạn gây nhầm lẫn trongnot(True) in [False, True]
Grijesh Chauhan

Câu trả lời:


730

Khai thác được ưu tiên 2.x , 3.x . Ưu tiên notthấp hơn so với in. Vì vậy, nó tương đương với:

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

Đây là cái bạn muốn:

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

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


279
@ Texom512: Tôi cũng khuyên bạn không bao giờ nên viết not(True); thích not True. Đầ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 notlà một chức năng, thì not(True) in ...không thể nào có thể not ((True) in ...). 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 ngụy trang nó như một hàm.
Ben

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

32
Trên thực tế, không bao giờ viết not True. Viết Falsethay thế.
Darkhogg

10
Có lẽ trong cuộc sống thực bạn sẽ không được viết not True, bạn muốn được viết một cái gì đó giống như not myfunc(x,y,z)nơi myfunclà một số chức năng mà lợi nhuận Truehay False.
Nate CK

3
@ BenC.R.Leggiero Đó là những gì tôi đã làm trong câu trả lời ban đầu và những người khác đã sửa nó. Phiên bản hiện tại đủ rõ ràng đối với tôi, tôi không nghĩ nó khó hiểu nếu không có dấu ngoặc đơn thừa, vì vấn đề chính đã được chỉ ra, hiểu phần còn lại là kỹ năng cơ bản của lập trình viên.
Yu Hao

76

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ằng cách phân tách mã. Trường hợp đầu tiên hoạt động 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], Falserõ ràng:

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

Thay vào đó (not(True)) in [False, True], những gì bạn muốn thể hiện là , như mong đợi True, và bạn có thể thấy tại sao:

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

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

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

5
@wim Tôi sẽ lập luận rằng việc triển khai mã byte không quan trọng bằng việc tháo gỡ thực tế. Các triển khai khác được đảm bảo để tạo ra một cái gì đó giống hệt nhau về mặt chức năng, do đó, việc hiểu một sự tháo gỡ cung cấp đủ hiểu biết để hiểu "lý do" chứ không phải "làm thế nào" ở mức thấp.
Alex Pana

36

Ưu tiên điều hành. inliên kết chặt chẽ hơn not, vì vậy biểu thức của bạn tương đương với not((True) in [False, True]).


33

Đó là tất cả về quyền ưu tiên của nhà điều hành ( inmạnh hơn not). Nhưng nó có thể được sửa một cách dễ dàng bằng cách thêm dấu ngoặc đơn vào đúng chỗ:

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

viết:

not(True) in [False, True]

giống như:

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

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


14

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

Nếu bạn cố gắng

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

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


13

Bên cạnh các câu trả lời khác có mức độ ưu tiên notthấp hơn in, thực tế, tuyên bố của bạn tương đương với:

not (True in [False, True])

Nhưng lưu ý rằng nếu bạn không tách biệt điều kiện của mình với các điều kiện khác, python sẽ sử dụng 2 vai trò ( precedencehoặc chaining) để phân tách điều đó và trong trường hợp này, python được sử dụng ưu tiên. Ngoài ra, lưu ý rằng nếu bạn muốn tách một điều kiện, bạn cần đặ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 khác của python trên các toán tử đang xâu chuỗi :

Dựa trên con trăn tài liệu:

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

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

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

Bởi vì python sẽ xâu chuỗi các câu lệnh 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 điều này cũng đúng với tất cả các So sánh, bao gồm các bài kiểm tra thành viên và các hoạt động kiểm tra danh tính theo các toán hạng sau:

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

Thí dụ :

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

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

7<x<20

tương đương với:

7<x and x<20   

6

Chúng ta hãy xem nó như là một hoạt động kiểm tra ngăn chặn bộ sưu tập: [False, True] là một danh sách chứa một số yếu 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]đưa ra "đối diện boolean", notkết quả của biểu thức trên (không có bất kỳ dấu ngoặc đơn nào để giữ quyền ưu tiên, vì incó độ ưu tiên lớn hơn nottoán tử). Do đó, not Truesẽ có 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).


6

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

Để thấy điều này theo 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 nhận được âm của hai bình phương, không phải là bình phương của hai âm (sẽ là bốn dương).

Điều gì nếu bạn đã muốn bình phương của hai âm? Rõ ràng, bạn sẽ thêm dấu ngoặc đơn:

>>> (-2)**2
4

Tuy nhiên, thật không hợp lý khi hy vọng những điều sau đây sẽ cho 4

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

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

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.