为啥“[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.x。 not
的优先级低于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
是一些返回True
或False
的函数。
@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】:
运算符优先级。 in
比not
绑定得更紧密,所以你的表达式等价于not((True) in [False, True])
。
【讨论】:
【参考方案4】:都是关于operator precedence(in
比not
强)。但是可以通过在正确的位置添加括号来轻松纠正:
(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 个角色(precedence
或 chaining
)来区分它,在这种情况下,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]
,即True
(False
包含在列表中)。
【讨论】:
【参考方案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,为啥它受到保护?