ทำไม“ ไม่ (จริง) ใน [เท็จจริง]” คืนเท็จ?


483

ถ้าฉันทำสิ่งนี้:

>>> False in [False, True]
True

Trueที่ส่งกลับ เพียงเพราะFalseอยู่ในรายการ

แต่ถ้าฉันทำ:

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

Falseที่ส่งกลับ โดยที่not(True)เท่ากับFalse:

>>> not(True)
False

ทำไม?



2
วงเล็บของคุณทำให้เกิดความสับสนnot(True) in [False, True]
Grijesh Chauhan

คำตอบ:


730

ความสำคัญประกอบ 2.x , 3.x ความสำคัญของการเป็นราคาที่ต่ำกว่าnot inดังนั้นจึงเท่ากับ:

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

นี่คือสิ่งที่คุณต้องการ:

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

เป็นจุด @ Ben ออก: ก็แนะนำให้ไม่เคยเขียนชอบnot(True) not Trueอดีตทำให้ดูเหมือนว่าการเรียกใช้งานในขณะที่notเป็นผู้ดำเนินการไม่ใช่ฟังก์ชั่น


279
@ Texom512: ฉันอยากจะแนะนำไม่เคยเขียนnot(True); not Trueชอบ ครั้งแรกทำให้ดูเหมือนว่าการเรียกใช้ฟังก์ชั่นซึ่งเป็นที่ที่ความสับสนของคุณมาจาก; ถ้าnotเป็นฟังก์ชั่นแล้วไม่อาจจะnot(True) in ... not ((True) in ...)คุณต้องรู้ว่ามันคือโอเปอเรเตอร์ (หรือท้ายที่สุดในสถานการณ์เช่นนี้) ดังนั้นคุณควรเขียนมันเหมือนโอเปอเรเตอร์ไม่ใช่การปลอมตัวเป็นฟังก์ชั่น
Ben

7
นอกจากนี้หากคุณจะใช้ช่องว่างเพื่อระบุความสำคัญเพื่อประโยชน์ของผู้อ่านก่อนอื่นต้องแน่ใจว่าคุณพูดถูก มันอาจจะตกลงที่จะเขียนก็ไม่ดีมากในการเขียนa + b*c + d a+b * c+dดังนั้นการnot(True)วัดก็ไม่ดีเช่นกัน
Steve Jessop

32
จริงๆแล้วอย่าเขียนnot Trueเลย เขียนFalseแทน
Darkhogg

10
สันนิษฐานว่าในชีวิตจริงคุณจะไม่ได้รับการเขียนnot Trueคุณต้องการจะเขียนสิ่งที่ต้องการnot myfunc(x,y,z)ที่myfuncเป็นฟังก์ชั่นบางอย่างที่ผลตอบแทนหรือTrue False
Nate CK

3
@ BenC.R.Leggiero นั่นคือสิ่งที่ฉันทำในคำตอบเดิมและคนอื่น ๆ ได้แก้ไขมัน รุ่นปัจจุบันชัดเจนเพียงพอสำหรับฉันฉันไม่คิดว่ามันยากที่จะเข้าใจหากไม่มีวงเล็บที่ซ้ำซ้อนเนื่องจากปัญหาหลักได้รับการชี้ให้เห็นการเข้าใจส่วนที่เหลือเป็นทักษะพื้นฐานของโปรแกรมเมอร์
Yu Hao

76

not x in y ได้รับการประเมินว่าเป็น x not in y

คุณสามารถดูว่าเกิดอะไรขึ้นโดยการถอดรหัส กรณีแรกใช้งานได้ตามที่คุณคาดหวัง:

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

กรณีที่สองประเมินไปTrue not in [False, True]ซึ่งFalseชัดเจน:

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

สิ่งที่คุณต้องการแสดงแทนคือ(not(True)) in [False, True]สิ่งที่คาดไว้Trueและคุณสามารถดูได้ว่าทำไม

>>> 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
มีผู้ชายอยู่เสมอdisแต่นี่เป็นคำตอบที่มีค่ามากเพราะมันแสดงให้เห็นว่าnot inใช้งานจริง
jamylak

21
Bytecode เป็นรายละเอียดการนำไปปฏิบัติของล่าม CPython นี่เป็นคำตอบ CPython สำหรับคำถาม Python อันที่จริงแล้วมันสามารถตอบได้ดีกว่าจากการอ้างอิงภาษาโดยตรง
Wim

5
@ ฉันจะยืนยันว่าการใช้งาน bytecode นั้นไม่สำคัญเท่ากับการถอดแยกชิ้นส่วนจริง การติดตั้งใช้งานอื่น ๆ นั้นรับประกันว่าจะสร้างบางสิ่งที่เหมือนกันในเชิงหน้าที่ดังนั้นการทำความเข้าใจการถอดแยกชิ้นส่วนหนึ่งจะให้ข้อมูลเชิงลึกมากพอที่จะเข้าใจ "ทำไม" และไม่ใช่ระดับต่ำ "วิธี"
Alex Pana

36

ผู้ประกอบการที่มีความสำคัญ inผูกให้กระชับยิ่งขึ้นกว่าดังนั้นการแสดงออกของคุณจะเทียบเท่ากับnotnot((True) in [False, True])


33

มันคือทั้งหมดที่เกี่ยวกับความสำคัญของผู้ประกอบการ ( inแข็งแรงกว่าnot) แต่สามารถแก้ไขได้อย่างง่ายดายโดยการเพิ่มวงเล็บในตำแหน่งที่ถูกต้อง:

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

การเขียน:

not(True) in [False, True]

เหมือนกัน:

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

ซึ่งดูว่าTrueอยู่ในรายการและส่งกลับ "ไม่" ของผลลัพธ์


14

มันกำลังประเมินผลnot True in [False, True]ซึ่งจะส่งคืนFalseเนื่องจากTrueอยู่ใน[False, True]

ถ้าคุณลอง

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

คุณได้รับผลลัพธ์ที่คาดหวัง


13

นอกเหนือจากคำตอบอื่น ๆ ที่กล่าวถึงลำดับความสำคัญnotต่ำกว่าinจริงๆแล้วข้อความของคุณจะเทียบเท่ากับ:

not (True in [False, True])

แต่โปรดทราบว่าถ้าคุณไม่แยกเงื่อนไขของคุณออกจากอีกอันหนึ่งไพ ธ อนจะใช้ 2 บทบาท ( precedenceหรือchaining) เพื่อแยกสิ่งนั้นออกและในกรณีนี้ไพ ธ อนใช้ความสำคัญกว่า นอกจากนี้โปรดทราบว่าหากคุณต้องการแยกเงื่อนไขคุณต้องใส่เงื่อนไขทั้งหมดไว้ในวงเล็บไม่ใช่แค่วัตถุหรือค่า:

(not True) in [False, True]

แต่ดังที่กล่าวไว้มีการดัดแปลงอีกอย่างหนึ่งโดย python ในโอเปอเรเตอร์ที่กำลังผูกมัด :

อ้างอิงจากเอกสารหลาม:

โปรดทราบว่าการเปรียบเทียบการทดสอบการเป็นสมาชิกและการทดสอบตัวตนทั้งหมดมีความสำคัญเท่ากันและมีคุณสมบัติการผูกมัดแบบซ้ายไปขวาตามที่อธิบายไว้ในส่วนการเปรียบเทียบ

ตัวอย่างเช่นผลลัพธ์ของข้อความสั่งต่อไปนี้คือFalse:

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

เพราะหลามจะโยงคำแถลงดังต่อไปนี้:

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

ซึ่งแน่นอนFalse and Trueว่าเป็นFalseที่

คุณสามารถสันนิษฐานได้ว่าวัตถุกลางจะถูกแชร์ระหว่าง 2 การดำเนินการกับวัตถุอื่น ๆ (เท็จในกรณีนี้)

และโปรดทราบว่ามันยังเป็นจริงสำหรับการเปรียบเทียบทั้งหมดรวมถึงการทดสอบการเป็นสมาชิกและการดำเนินการทดสอบเอกลักษณ์ซึ่งมีตัวถูกดำเนินการดังต่อไปนี้:

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

ตัวอย่าง:

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

อีกตัวอย่างที่มีชื่อเสียงคือช่วงตัวเลข:

7<x<20

ซึ่งเท่ากับ:

7<x and x<20   

6

มาดูกันว่าเป็นการดำเนินการตรวจสอบการ จำกัด การรวบรวม: [False, True]เป็นรายการที่มีองค์ประกอบบางอย่าง

การแสดงออกTrue in [False, True]กลับTrueมาเป็นTrueเป็นองค์ประกอบที่มีอยู่ในรายการ

ดังนั้นnot True in [False, True]ให้ "บูลีนตรงข้าม" ซึ่งเป็นnotผลมาจากการแสดงออกข้างต้น (ไม่มีวงเล็บใด ๆ เพื่อรักษาลำดับความสำคัญเช่นเดียวกับที่inมีความสำคัญมากกว่าnotผู้ประกอบการ) ดังนั้นnot Trueจะส่งผลให้Falseจะส่งผลให้

ในทางกลับ(not True) in [False, True]กันเท่ากับFalse in [False, True]ซึ่งคือTrue( Falseมีอยู่ในรายการ)


6

เพื่อชี้แจงเพิ่มเติมเกี่ยวกับคำตอบอื่น ๆ การเพิ่มวงเล็บหลังจากตัวดำเนินการ unary ไม่เปลี่ยนความสำคัญ not(True)ไม่ได้ทำให้ผูกให้กระชับยิ่งขึ้นไปnot มันเป็นเพียงชุดซ้ำซ้อนวงเล็บรอบTrue มันมากเช่นเดียวกับTrue (True) in [True, False]วงเล็บไม่ทำอะไรเลย หากคุณต้องการให้การเย็บเล่มมีความแน่นมากขึ้นคุณต้องใส่วงเล็บล้อมรอบนิพจน์ทั้งหมดซึ่งหมายถึงทั้งตัวดำเนินการและตัวถูกดำเนินการเช่น(not True) in [True, False]ถ้าคุณต้องการที่จะมีผลผูกพันแน่นมากขึ้นคุณจะต้องใส่วงเล็บรอบการแสดงออกทั้งความหมายทั้งผู้ประกอบการและถูกดำเนินการคือ

หากต้องการดูอีกวิธีหนึ่งให้พิจารณา

>>> -2**2
-4

** ผูกแน่นกว่า -ซึ่งเป็นสาเหตุที่คุณได้ลบ 2 กำลังสองไม่ใช่กำลังสองของลบ (ซึ่งจะเป็นบวก 4)

ถ้าคุณต้องการสแควร์ของลบสองตัว? เห็นได้ชัดว่าคุณจะเพิ่มวงเล็บ:

>>> (-2)**2
4

อย่างไรก็ตามมันไม่สมเหตุสมผลที่จะคาดหวังสิ่งต่อไปนี้ที่จะให้ 4

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

เพราะเป็นเช่นเดียวกับ-(2) -2วงเล็บไม่ทำอะไรเลยอย่างแน่นอน not(True)เหมือนกันทุกประการ

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.