Python `ถ้า x ไม่ใช่ None 'หรือ` ถ้าไม่ใช่ x ไม่ใช่ None'?


746

ฉันคิดเสมอของif not x is Noneรุ่นที่จะมีความชัดเจนมากขึ้น แต่ของ Google คู่มือสไตล์และPEP-8if x is not Noneใช้งานทั้ง มีความแตกต่างเล็กน้อยในการทำงาน (ฉันไม่ได้คาดหวังไว้) และมีกรณีใดบ้างที่ไม่เหมาะสม (ทำให้อีกฝ่ายเป็นผู้ชนะที่ชัดเจนสำหรับการประชุมของฉัน) *

* ผมหมายถึงเดี่ยว ๆ Noneมากกว่าแค่

... เพื่อเปรียบเทียบซิงเกิลตันแบบไม่มี ใช้เป็นหรือไม่


8
is notเป็นผู้ดำเนินการที่ถูกต้อง กด!=ไลค์ ถ้าคุณต้องการnot x is Noneแล้วคุณยังจะชอบมากกว่าnot a == b a != b
Tomasz Gandor

@TomaszGandor ผมไม่ได้มีความเห็นเกี่ยวกับเรื่องนี้not x is None(คำตอบที่นี่เชื่อฉัน) - มันเป็น แต่ที่น่าสังเกตว่าเป็นรูปแบบที่ต้องการในหลามเมื่อเทียบกับnot a == b a != b
orokusaki

4
@orokusaki เป็นnot a == bสไตล์ที่ต้องการจริงๆเหรอ? !=ฉันไม่เคยเห็นมันทำและวิธีการที่ทุกคนผมมองการใช้งานทั้งหมด
ไมค์ - SMT

2
นับการอ่าน @orokusaki ในหลามดังนั้นจึงเป็นรูปแบบที่ต้องการจะใช้หนึ่งในผู้ประกอบการ!=แทนของทั้งสองผู้ประกอบการ,not ==
Jeyekomon

คำตอบ:


995

ไม่มีความแตกต่างด้านประสิทธิภาพขณะที่พวกเขาคอมไพล์ด้วยรหัสไบต์เดียวกัน:

Python 2.6.2 (r262:71600, Apr 15 2009, 07:20:39)
>>> import dis
>>> def f(x):
...    return x is not None
...
>>> dis.dis(f)
  2           0 LOAD_FAST                0 (x)
              3 LOAD_CONST               0 (None)
              6 COMPARE_OP               9 (is not)
              9 RETURN_VALUE
>>> def g(x):
...   return not x is None
...
>>> dis.dis(g)
  2           0 LOAD_FAST                0 (x)
              3 LOAD_CONST               0 (None)
              6 COMPARE_OP               9 (is not)
              9 RETURN_VALUE

Stylistically not x is yฉันพยายามที่จะหลีกเลี่ยง แม้ว่าคอมไพเลอร์จะรักษามันเป็นผู้อ่านอาจเข้าใจผิดมนุษย์สร้างเป็นnot (x is y) (not x) is yถ้าฉันเขียนx is not yแล้วไม่มีความกำกวม


103
x is (not y)เว้นแต่อ่านคนเดียวคิดว่ามันเป็น แต่ฉันมักจะเห็นด้วยกับคุณด้วยเหตุผลอื่นของคุณ
Etaoin

24
นอกจากนี้ "ไม่" ไม่ชัดเจนในบริบทนี้ "ถ้า a ไม่ใช่ไม่ใช่และ b คือไม่มี:" vs "ถ้าไม่ใช่ a ไม่มีและ b คือไม่มี:"
Gordon Wrigley

45
ผู้ประกอบการควรเป็น "aint"
bean

216

คู่มือสไตล์ของGoogle และPythonเป็นแนวทางปฏิบัติที่ดีที่สุด:

if x is not None:
    # Do something about x

การใช้not xอาจทำให้เกิดผลลัพธ์ที่ไม่พึงประสงค์

ดูด้านล่าง:

>>> x = 1
>>> not x
False
>>> x = [1]
>>> not x
False
>>> x = 0
>>> not x
True
>>> x = [0]         # You don't want to fall in this one.
>>> not x
False

คุณอาจสนใจที่จะดูว่าตัวอักษรใดได้รับการประเมินTrueหรือFalseใน Python:


แก้ไขสำหรับความคิดเห็นด้านล่าง:

ฉันแค่ทำการทดสอบเพิ่มเติม not x is Noneไม่ปฏิเสธครั้งแรกแล้วเมื่อเทียบกับx Noneในความเป็นจริงดูเหมือนว่าisโอเปอเรเตอร์จะมีลำดับความสำคัญสูงกว่าเมื่อใช้แบบนั้น:

>>> x
[0]
>>> not x is None
True
>>> not (x is None)
True
>>> (not x) is None
False

ดังนั้นnot x is Noneในความเห็นที่ถูกต้องฉันควรหลีกเลี่ยงสิ่งที่ดีที่สุด


แก้ไขเพิ่มเติม:

ฉันเพิ่งทำการทดสอบเพิ่มเติมและสามารถยืนยันได้ว่าข้อคิดเห็นของ bukzor นั้นถูกต้อง (อย่างน้อยฉันก็ไม่สามารถพิสูจน์ได้)

วิธีการนี้มีผลแน่นอนเป็นif x is not None if not x is Noneฉันยืนแก้ไขแล้ว ขอบคุณ bukzor

แต่คำตอบของฉันยังคงยืน: ใช้ทั่วไปif x is not None:]


131

ควรเขียนโค้ดเพื่อให้โปรแกรมเมอร์เข้าใจได้ง่ายและคอมไพเลอร์หรือล่ามที่สอง โครงสร้าง "ไม่ได้" มีลักษณะคล้ายกับภาษาอังกฤษอย่างใกล้ชิดกว่า "ไม่เป็น"


33

งูหลามif x is not Noneหรือif not x is None?

TLDR: คอมไพเลอร์ bytecode แยกพวกเขาทั้งสองไปx is not None- if x is not Noneดังนั้นเพื่อประโยชน์ในการอ่านของการใช้งาน

การอ่าน

เราใช้ Python เพราะเราให้ความสำคัญกับสิ่งต่าง ๆ เช่นความสามารถในการอ่านของมนุษย์ความสามารถในการใช้งานและความถูกต้องของกระบวนทัศน์ที่หลากหลายของการเขียนโปรแกรมมากกว่าประสิทธิภาพ

Python ปรับให้เหมาะสมสำหรับการอ่านโดยเฉพาะอย่างยิ่งในบริบทนี้

แยกและรวบรวม Bytecode

การnot ผูกนั้นอ่อนแอกว่าisดังนั้นจึงไม่มีความแตกต่างทางตรรกะที่นี่ ดูเอกสารประกอบ :

โอเปอเรเตอร์isและis notทดสอบการระบุตัวตนของวัตถุ: x is yเป็นจริงถ้า x และ y เป็นวัตถุเดียวกัน x is not yให้ค่าความจริงผกผัน

is notมีให้เฉพาะสำหรับในหลามไวยากรณ์เป็นการปรับปรุงการอ่านภาษา:

comp_op: '<'|'>'|'=='|'>='|'<='|'<>'|'!='|'in'|'not' 'in'|'is'|'is' 'not'

และมันก็เป็นองค์ประกอบที่รวมกันของไวยากรณ์เช่นกัน

แน่นอนว่ามันไม่ได้แยกวิเคราะห์เหมือนกัน:

>>> import ast
>>> ast.dump(ast.parse('x is not None').body[0].value)
"Compare(left=Name(id='x', ctx=Load()), ops=[IsNot()], comparators=[Name(id='None', ctx=Load())])"
>>> ast.dump(ast.parse('not x is None').body[0].value)
"UnaryOp(op=Not(), operand=Compare(left=Name(id='x', ctx=Load()), ops=[Is()], comparators=[Name(id='None', ctx=Load())]))"

แต่แล้วคอมไพเลอร์ไบต์จริงจะแปลnot ... isไปis not:

>>> import dis
>>> dis.dis(lambda x, y: x is not y)
  1           0 LOAD_FAST                0 (x)
              3 LOAD_FAST                1 (y)
              6 COMPARE_OP               9 (is not)
              9 RETURN_VALUE
>>> dis.dis(lambda x, y: not x is y)
  1           0 LOAD_FAST                0 (x)
              3 LOAD_FAST                1 (y)
              6 COMPARE_OP               9 (is not)
              9 RETURN_VALUE

is notดังนั้นเพื่อประโยชน์ของการอ่านและการใช้ภาษาที่ก็ตั้งใจใช้โปรด

ที่จะไม่ใช้มันไม่ฉลาด


"การnotผูกนั้นอ่อนแอกว่าisดังนั้นจึงไม่มีความแตกต่างทางตรรกะที่นี่" - ยกเว้นว่า Python ไม่จำเป็นต้องบังคับใช้ตัวตนเชิงตรรกะและพีชคณิตให้ถือ (ไม่มีเหตุผลที่แท้จริงสำหรับ(1 + 2)*3การประเมินเช่นเดียวกัน1*3 + 2*3) เห็นได้ชัดว่านี่คือการโกงหลามและเพิ่มประสิทธิภาพUNARY_NOTออกไป
Alexey

30

คำตอบนั้นง่ายกว่าที่ผู้คนทำ

ไม่มีข้อได้เปรียบด้านเทคนิคอย่างใดอย่างหนึ่งและ "x ไม่ใช่ y" คือสิ่งที่ทุกคนใช้ซึ่งทำให้ผู้ชนะชัดเจน ไม่สำคัญว่าจะ "ดูเหมือนภาษาอังกฤษมากกว่า" หรือไม่ ทุกคนใช้มันซึ่งหมายความว่าผู้ใช้ Python ทุกคน - แม้แต่ผู้ใช้ภาษาจีนที่มีภาษา Python ไม่เหมือนใคร - จะเข้าใจได้อย่างรวดเร็วโดยที่ไวยากรณ์ที่พบได้น้อยกว่าเล็กน้อยจะใช้เวลาสองรอบในการแยกวิเคราะห์

อย่าต่างไปเพียงเพื่อความแตกต่างอย่างน้อยก็ในสาขานี้


11

is notผู้ประกอบการเป็นที่ต้องการมากกว่ากวนผลมาจากการisด้วยเหตุผลโวหาร " if x is not None:" อ่านเหมือนภาษาอังกฤษ แต่ " if not x is None:" ต้องมีความเข้าใจลำดับความสำคัญของผู้ปฏิบัติงานและไม่อ่านภาษาอังกฤษ

หากมีความแตกต่างด้านผลงานของฉันเงินของฉันอยู่บนis notแต่นี่เกือบจะแน่นอนไม่ได้เป็นแรงจูงใจสำหรับการตัดสินใจที่จะชอบเทคนิคที่ เห็นได้ชัดว่ามันจะขึ้นอยู่กับการใช้งาน เนื่องจากisไม่ใช่ overridable จึงควรปรับความแตกต่างได้อย่างง่ายดาย


9

ส่วนตัวผมใช้

if not (x is None):

ซึ่งเข้าใจได้ทันทีโดยไม่ต้องมีความกำกวมโดยโปรแกรมเมอร์ทุกคนแม้แต่ผู้ที่ไม่เชี่ยวชาญในไวยากรณ์ Python


5
ข้อโต้แย้งที่เป็นธรรมที่ฉันเห็นด้วย แต่ฉันเชื่อว่าอาร์กิวเมนต์ของการติดตามลักษณะที่เป็นสำนวนนั้นแข็งแกร่งกว่า
clacke

2

if not x is Noneคล้ายกับภาษาโปรแกรมอื่น ๆ มากกว่า แต่if x is not Noneแน่นอนว่าฉันจะชัดเจนกว่า (และถูกต้องตามหลักไวยากรณ์ในภาษาอังกฤษ) สำหรับฉัน

ที่กล่าวว่าดูเหมือนว่ามันเป็นสิ่งที่ชอบมากกว่าสำหรับฉัน


0

ฉันต้องการรูปแบบที่อ่านได้x is not y มากกว่าที่ฉันคิดว่าในที่สุดวิธีการเขียนรหัสการจัดการลำดับความสำคัญของตัวดำเนินการในที่สุดเพื่อสร้างรหัสที่อ่านได้มากขึ้น

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