为啥“[False, True] 中的 not(True)”返回 False?

Posted

技术标签:

【中文标题】为啥“[False, True] 中的 not(True)”返回 False?【英文标题】:Why does "not(True) in [False, True]" return False?为什么“[False, True] 中的 not(True)”返回 False? 【发布时间】:2015-10-03 23:04:01 【问题描述】:

如果我这样做:

>>> False in [False, True]
True

返回True。仅仅因为False 在列表中。

但如果我这样做:

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

返回False。而not(True) 等于False

>>> not(True)
False

为什么?

【问题讨论】:

相关***.com/questions/31354429/… 你的括号在not(True) in [False, True]中混淆了 【参考方案1】:

运算符优先级 2.x, 3.xnot 的优先级低于in。所以相当于:

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

这就是你想要的:

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

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

【讨论】:

@Texom512:我还建议不要写not(True);更喜欢not True。第一个使它看起来像一个函数调用,这就是您的困惑的来源;如果not 是一个函数,那么not(True) in ... 不可能是not ((True) in ...)。你必须知道它是一个运算符(或者你最终会遇到这种情况),所以你应该把它写成一个运算符,而不是把它伪装成一个函数。 另外,如果您要使用空格来表示优先级以方便读者阅读,请首先确保您是对的。写a + b*c + d 可能还可以,写a+b * c+d 很糟糕。所以not(True) 从这个角度来看也很糟糕。 实际上,从不not True。请改写False 大概在现实生活中你不会写not True,你会写像not myfunc(x,y,z)这样的东西,其中myfunc是一些返回TrueFalse的函数。 @BenC.R.Leggiero 这就是我在the original answer 中所做的,其他人已经更正了。目前的版本对我来说已经很清楚了,我觉得没有多余的括号很难理解,既然已经指出了关键问题,那么理解剩下的就是程序员的基本技能了。【参考方案2】:

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        

【讨论】:

总有一个人使用dis,但这是一个非常有价值的答案,因为它表明实际上使用了not in 字节码是 CPython 解释器的一个实现细节。这是一个 Python 问题的 CPython 答案,实际上可以直接从语言参考中更好地回答。 @wim 我认为字节码实现不如实际反汇编重要。其他实现可以保证生成功能相同的东西,因此理解一个反汇编可以提供足够的洞察力来理解“为什么”而不是低级“如何”。【参考方案3】:

运算符优先级。 innot 绑定得更紧密,所以你的表达式等价于not((True) in [False, True])

【讨论】:

【参考方案4】:

都是关于operator precedence(innot 强)。但是可以通过在正确的位置添加括号来轻松纠正:

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

写作:

not(True) in [False, True]

同理:

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

查看True 是否在列表中并返回结果的“非”。

【讨论】:

【参考方案5】:

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

如果你尝试

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

你得到了预期的结果。

【讨论】:

【参考方案6】:

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

not (True in [False, True])

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

(not True) in [False, True]

但如前所述,python 对运算符的另一个修改是 chaining

基于pythondocumentation

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

例如下面语句的结果是False:

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

因为 python 会像下面这样链接语句:

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

究竟是False and True,即False

您可以假设中心对象将在 2 个操作和其他对象之间共享(在这种情况下为 False)。

请注意,所有比较也是如此,包括跟随操作数的成员资格测试和身份测试操作:

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

例子:

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

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

7<x<20

等于:

7<x and x<20   

【讨论】:

【参考方案7】:

让我们把它看成一个集合包含检查操作:[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],即TrueFalse 包含在列表中)。

【讨论】:

【参考方案8】:

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

要换个角度看,请考虑

>>> -2**2
-4

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

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

>>> (-2)**2
4

但是,期望以下提供4 是不合理的

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

因为-(2)-2 相同。括号完全没有任何作用。 not(True) 完全一样。

【讨论】:

以上是关于为啥“[False, True] 中的 not(True)”返回 False?的主要内容,如果未能解决你的问题,请参考以下文章

为啥 DataGridView 上的 DoubleBuffered 属性默认为 false,为啥它受到保护?

为啥需要softmax函数?为啥不简单归一化?

为啥 g++ 需要 libstdc++.a?为啥不是默认值?

为啥或为啥不在 C++ 中使用 memset? [关闭]

为啥临时变量需要更改数组元素以及为啥需要在最后取消设置?

为啥 CAP 定理中的 RDBMS 分区不能容忍,为啥它可用?