为什么"False,True]中的"not(True)"返回False?

Tex*_*512 477 python python-2.7 python-3.x

如果我这样做:

>>> False in [False, True]
True
Run Code Online (Sandbox Code Playgroud)

那回来了True.只是因为False在列表中.

但如果我这样做:

>>> not(True) in [False, True]
False
Run Code Online (Sandbox Code Playgroud)

那回来了False.而not(True)等于False:

>>> not(True)
False
Run Code Online (Sandbox Code Playgroud)

为什么?

Yu *_*Hao 727

运算符优先级 2.x,3.x.优先级not低于in.所以它相当于:

>>> not ((True) in [False, True])
False
Run Code Online (Sandbox Code Playgroud)

这就是你想要的:

>>> (not True) in [False, True]
True
Run Code Online (Sandbox Code Playgroud)

正如@Ben所指出的那样:建议永远不要写not(True),更喜欢not True.前者使它看起来像一个函数调用,而它not是一个运算符,而不是一个函数.

  • @ Texom512:我也建议永远不要写'不(真)`; 更喜欢'不是真'.第一个使它看起来像一个函数调用,这是你的困惑来自; 如果`not`是一个函数,则``中的'not(True)'可能不是'not((True)in ...)`.你必须知道它是一个操作符(或者你最终会遇到这样的情况),所以你应该像操作符一样编写它,而不是把它伪装成一个函数. (278认同)
  • 实际上,**从不**写'不是真'.写'假'代替. (32认同)
  • 据推测,在现实生活中,你不会写"不是真的",你会写一些像'不是myfunc(x,y,z)`,其中`myfunc`是一些返回'True`或'False`的函数. (10认同)
  • 此外,如果您要使用间距来指示读者的利益优先级,请首先确保您是对的.写"a + b*c + d"可能没问题,写"a + b*c + d"非常糟糕.所以`not(True)`也不好. (7认同)
  • @ BenC.R.Leggiero这就是我在[原始答案](http://stackoverflow.com/revisions/31421411/1)中所做的,其他人已经纠正了它.目前的版本对我来说已经足够清楚了,我认为没有多余的括号很难理解,因为已经指出了关键问题,理解其余部分是程序员的基本技能. (3认同)

Ros*_*ews 74

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
Run Code Online (Sandbox Code Playgroud)

第二种情况,评估为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        
>>> 
Run Code Online (Sandbox Code Playgroud)

您要表达的是(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        
Run Code Online (Sandbox Code Playgroud)

  • 字节码是CPython解释器的实现细节.这是对Python问题的CPython答案,事实上它可以直接从语言参考中得到更好的回答. (21认同)
  • 总有一个人有'dis`,但这是一个非常有价值的答案,因为它表明实际上是'不在' (13认同)
  • @wim我认为字节码实现并不像实际的反汇编那么重要.其他实现保证生成功能相同的东西,因此理解一个反汇编提供了足够的洞察力来理解"为什么"而不是低级"如何". (5认同)

小智 35

运算符优先级.in绑定比紧not,所以你的表达相当于not((True) in [False, True]).


alf*_*sin 33

这都是关于运算符优先级(in强于not).但是可以通过在正确的位置添加括号来轻松纠正:

(not(True)) in [False, True]  # prints true
Run Code Online (Sandbox Code Playgroud)

写作:

not(True) in [False, True]
Run Code Online (Sandbox Code Playgroud)

是这样的:

not((True) in [False, True])
Run Code Online (Sandbox Code Playgroud)

看起来是否True在列表中并返回结果的"not".


use*_*636 14

据评估为not True in [False, True],返回False是因为True[False, True]

如果你试试

>>>(not(True)) in [False, True]
True
Run Code Online (Sandbox Code Playgroud)

你得到了预期的结果.


Kas*_*mvd 13

除了提到优先级的其他答案not低于in,实际上你的陈述相当于:

not (True in [False, True])
Run Code Online (Sandbox Code Playgroud)

但请注意,如果你不将你的条件与其他条件分开,python将使用2个角色(precedencechaining)来分隔它,在这种情况下python使用优先级.另请注意,如果要分离条件,则需要将所有条件放在括号中,而不仅仅是对象或值:

(not True) in [False, True]
Run Code Online (Sandbox Code Playgroud)

但正如前面提到的,python对链接的运算符进行了另一种修改:

基于python 文档:

请注意,比较,成员资格测试和身份测试都具有相同的优先级,并具有从"比较"部分中所述的从左到右的链接功能.

例如,以下语句的结果是False:

>>> True == False in [False, True]
False
Run Code Online (Sandbox Code Playgroud)

因为python会将语句链接如下:

(True == False) and (False in [False, True])
Run Code Online (Sandbox Code Playgroud)

这到底是False and True那是False.

您可以假设中心对象将在2个操作和其他对象之间共享(在本例中为False).

请注意,对于所有比较,它也适用,包括跟随操作数的成员资格测试和身份测试操作:

in, not in, is, is not, <, <=, >, >=, !=, ==
Run Code Online (Sandbox Code Playgroud)

示例:

>>> 1 in [1,2] == True
False
Run Code Online (Sandbox Code Playgroud)

另一个着名的例子是数字范围:

7<x<20
Run Code Online (Sandbox Code Playgroud)

等于:

7<x and x<20   
Run Code Online (Sandbox Code Playgroud)


Nic*_*kis 6

让我们将其视为集合包含检查操作:[False, True]是包含一些元素的列表.

表达式True in [False, True]返回True,True列表中包含的元素也是如此.

因此,not True in [False, True]给出"boolean opposite",not即上述表达式的结果(没有任何括号来保留优先级,因为它in具有比not运算符更高的优先级).因此,not True将导致False.

另一方面,(not True) in [False, True]等于False in [False, True],True(False包含在列表中).


asm*_*rer 6

为了澄清其他一些答案,一元运算符添加括号不会改变其优先级.not(True)不会使not绑定更紧密True.它只是一组冗余的括号True.它与...大致相同(True) in [True, False].括号不做任何事情.如果希望绑定更紧密,则必须将括号放在整个表达式周围,这意味着运算符和操作数,即(not True) in [True, False].

为了看到另一种方式,请考虑

>>> -2**2
-4
Run Code Online (Sandbox Code Playgroud)

**-这更紧密地绑定,这就是为什么你得到两个平方的负数,而不是负二的平方(这将是正四).

如果你确实想要负二的平方怎么办?显然,你要添加括号:

>>> (-2)**2
4
Run Code Online (Sandbox Code Playgroud)

但是,期望以下内容给出是不合理的 4

>>> -(2)**2
-4
Run Code Online (Sandbox Code Playgroud)

因为-(2)是一样的-2.括号什么都不做.not(True)是完全一样的.