"x不在y中"或"不是x在y中"

117

在测试成员资格时,我们可以使用:

x not in y
或者,另一种选择是:
not x in y

根据 xy 的不同,这个表达式可能有许多可能的语境。例如,它可以用于子字符串检查、列表成员资格、字典键存在性等。

  • 这两种形式总是等效的吗?
  • 是否有优选语法?
6个回答

128

它们总是给出相同的结果。

事实上,not 'ham' in 'spam and eggs' 被特殊处理为执行单个的 "not in" 操作,而不是执行 "in" 操作并取反结果:

>>> import dis

>>> def notin():
    'ham' not in 'spam and eggs'
>>> dis.dis(notin)
  2           0 LOAD_CONST               1 ('ham')
              3 LOAD_CONST               2 ('spam and eggs')
              6 COMPARE_OP               7 (not in)
              9 POP_TOP             
             10 LOAD_CONST               0 (None)
             13 RETURN_VALUE    

>>> def not_in():
    not 'ham' in 'spam and eggs'
>>> dis.dis(not_in)
  2           0 LOAD_CONST               1 ('ham')
              3 LOAD_CONST               2 ('spam and eggs')
              6 COMPARE_OP               7 (not in)
              9 POP_TOP             
             10 LOAD_CONST               0 (None)
             13 RETURN_VALUE    

>>> def not__in():
    not ('ham' in 'spam and eggs')
>>> dis.dis(not__in)
  2           0 LOAD_CONST               1 ('ham')
              3 LOAD_CONST               2 ('spam and eggs')
              6 COMPARE_OP               7 (not in)
              9 POP_TOP             
             10 LOAD_CONST               0 (None)
             13 RETURN_VALUE        

>>> def noteq():
    not 'ham' == 'spam and eggs'
>>> dis.dis(noteq)
  2           0 LOAD_CONST               1 ('ham')
              3 LOAD_CONST               2 ('spam and eggs')
              6 COMPARE_OP               2 (==)
              9 UNARY_NOT           
             10 POP_TOP             
             11 LOAD_CONST               0 (None)
             14 RETURN_VALUE      

一开始我以为它们总是给出相同的结果,但是not本身只是一个优先级较低的逻辑取反运算符,可以像任何其他布尔表达式一样应用于a in b,而not in则是一种方便和清晰的分离运算符。

上面的反汇编结果很有启示性!看起来,虽然not显然是一个逻辑取反运算符,但形式not a in b是特殊情况,因此它实际上并没有使用通用运算符。这使得not a in b字面上与a not in b相同,而不仅仅是产生相同值的表达式。


5
请记住,这只是一个实现细节。我甚至找不到文档中提到“not x in xs”的任何内容。 - phant0m
1
@phant0m 绝对正确;你应该这样考虑 not x in xs,即 not (x in xs)。但是它被解析成与 x not in xs 完全相同的字节码实现的事实非常清楚地表明它们必须始终相同,而不像 not x == y vs x != y 这样的东西应该给出相同的结果,但不一定(取决于涉及的 __eq____ne__ 的实现)。 - Ben
13
你遇到了一个名为CPython Peephole Optimization的编译时优化,其他Python实现如Jython和IronPython可以忽略或者复制它(因为它不是语言规范的一部分)。请注意,本次翻译并不包含解释和额外内容。 - Martijn Pieters

22

  1. 没有,它们是一样的。

    操作符not in被定义为与in相反的真值。

    Python文档

  2. 我认为not in更受欢迎,因为它更明显,并且他们为其添加了一个特殊情况。


11

2

其他人已经非常清楚地表明这两个语句,在很低的水平上是等价的。

然而,我认为还没有任何人强调过,既然这样留下了选择的余地,你应该选择让你的代码尽可能容易阅读的形式。

请选择最容易阅读的形式。

并不一定要尽可能容易阅读对于任何人,即使这当然是一个很好的目标。相反,确保代码尽可能容易阅读对于你自己,因为你最有可能回来查看这段代码并尝试阅读它。


1
如果您正在一个大团队中工作或者编写的代码可能长时间不被触及,那么有可能别人会来维护它。 - Tommy Herbert

1

在Python中,没有差别。也没有偏好。


0

从语法上讲,它们是相同的语句。我会很快地说'ham' not in 'spam and eggs'传达了更清晰的意图,但我见过代码和情境,其中not 'ham' in 'spam and eggs'比另一个传达了更清晰的含义。


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