"x not in"与"not x in"的区别

78

我注意到这两者的作用相同:

if x not in listif not x in list.

在某些情况下,它们之间是否有区别? 是否有其存在的原因,还是只是因为有些人更自然地写其中一种?

在其他人的代码中,哪一种更常见?


1
关闭一个较旧的问题并将其作为一个较新问题的重复是完全可以接受的。请参见 http://meta.stackoverflow.com/q/255410,http://meta.stackexchange.com/a/147651。 - ThisSuitIsBlackNot
5个回答

102

这两种形式生成的字节码完全相同,您可以清楚地验证:

>>> import dis
>>> dis.dis(compile('if x not in d: pass', '', 'exec'))
  1           0 LOAD_NAME                0 (x)
              3 LOAD_NAME                1 (d)
              6 COMPARE_OP               7 (not in)
              9 JUMP_IF_FALSE            4 (to 16)
             12 POP_TOP             
             13 JUMP_FORWARD             1 (to 17)
        >>   16 POP_TOP             
        >>   17 LOAD_CONST               0 (None)
             20 RETURN_VALUE        
>>> dis.dis(compile('if not x in d: pass', '', 'exec'))
  1           0 LOAD_NAME                0 (x)
              3 LOAD_NAME                1 (d)
              6 COMPARE_OP               7 (not in)
              9 JUMP_IF_FALSE            4 (to 16)
             12 POP_TOP             
             13 JUMP_FORWARD             1 (to 17)
        >>   16 POP_TOP             
        >>   17 LOAD_CONST               0 (None)
             20 RETURN_VALUE        

很明显,它们在语义上是相同的。

就风格而言,PEP 8没有提到这个问题。

就我个人而言,我强烈推荐使用 if x not in y 的形式--这使得它立即清楚了 not in 是单一运算符,并且“读起来像是英语”。if not x in y 可能会让一些读者误认为它的意思是 if (not x) in y,读起来有点不像英语,并且没有任何补偿优势。


8
PEP 8提到了类似的偏好:“使用is not运算符而不是not ... is。虽然这两个表达式在功能上是相同的,但前者更易读且更受推崇。” - Walter Tross

8
>>> dis.dis(lambda: a not in b)
1           0 LOAD_GLOBAL              0 (a)
          3 LOAD_GLOBAL              1 (b)
          6 COMPARE_OP               7 (not in)
          9 RETURN_VALUE      

>>> dis.dis(lambda: not a in b)
1           0 LOAD_GLOBAL              0 (a)
          3 LOAD_GLOBAL              1 (b)
          6 COMPARE_OP               7 (not in)
          9 RETURN_VALUE  

当你使用“not a in b”时,它需要被转换为“not in”。因此,正确的方式是“a not in b”。

3

not x in L没有明确禁止,因为那样做是愚蠢的。x not in L是明确允许的(尽管它编译成相同的字节码),因为它更易读。

然而,大家都使用x not in L


3
当你写 a not in b 时,它使用的是 not in 运算符,而 not a in b 使用的是 in 运算符,然后取反结果。但是 not in 运算符被定义为返回与 not a in b 相同的结果,因此它们完全相同。来自 文档

运算符 innot in 用于测试集合成员资格。如果 x 是集合 s 的成员,则 x in s 计算结果为真,否则为假。 x not in s 返回 x in s 的否定。

类似地,还有 a is not bnot a is b
额外的语法是添加的,因为它使人更容易自然地阅读它。

1
奇怪的是,当您使用dis模块时,它显示它们都使用not in进行比较,尽管文档中说的不是这样... - avacariu

0

这只是个人偏好。你也可以比较if x != 3if not x == 3。你展示的这两个表达式之间没有区别。


15
不相同。!= 调用 __ne__,而 == 调用 __eq__。在特定情况下,你的示例可能会产生不同的结果。 - John La Rooy
2
足够正确。我应该加上“撇开歪曲不谈”! - Ned Batchelder

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接