Python的(__contains __)运算符返回一个bool,其值既不是True也不是False

use*_*478 32 python membership boolean comparison-operators

正如预期的那样,空元组不包含1

>>> 1 in ()
False
Run Code Online (Sandbox Code Playgroud)

False返回的值不等于False

>>> 1 in () == False
False
Run Code Online (Sandbox Code Playgroud)

从另一个角度看,in操作员返回bool既不是也不TrueFalse:

>>> type(1 in ())
<type 'bool'>
>>> 1 in () == True, 1 in () == False
(False, False)
Run Code Online (Sandbox Code Playgroud)

但是,如果原始表达式带括号,则恢复正常行为

>>> (1 in ()) == False
True
Run Code Online (Sandbox Code Playgroud)

或其值存储在变量中

>>> value = 1 in ()
>>> value == False
True
Run Code Online (Sandbox Code Playgroud)

在Python 2和Python 3中都观察到了这种行为.

你能解释一下发生了什么吗?

Mar*_*ers 45

你正在进行比较运算符链接; 1 in () == False没有意思(1 in ()) == False.

相反,比较是链接的,表达式的确意味着:

(1 in ()) and (() == False)
Run Code Online (Sandbox Code Playgroud)

因为(1 in ())已经是假的,所以链式表达式的后半部分被完全忽略(因为False and something_else返回False任何值的值something_else).

请参阅比较表达式文档:

比较可以任意链接,例如,x < y <= z等同于x < y and y <= z,除了y仅评估一次(但在两种情况下z都没有被评估,当x < y发现是假的时).

对于记录,<,>,==,>=,<=,!=,is,is not,innot in都是比较运算符(如本弃用<>).

一般来说,不要与布尔值进行比较; 只是测试表达本身.如果你必须测试一个布尔文字,至少使用括号和is运算符,True并且False是单例,就像None:

>>> (1 in ()) is False
True
Run Code Online (Sandbox Code Playgroud)

当涉及整数时,这仍然会更加混乱.Python的bool类型是子类int1.因此,False == 0确实如此True == 1.因此,可以想象创建几乎看起来很健全的链式操作:

3 > 1 == True
Run Code Online (Sandbox Code Playgroud)

因为是真实的3 > 1并且1 == True都是真实的.但表达式:

3 > 2 == True
Run Code Online (Sandbox Code Playgroud)

是假的,因为2 == True是假的.

1 历史原因的子类; Python并不总是有类型和重载整数与布尔意义就像C一样.使子类保持较旧的代码工作. boolintboolbool

  • @ user2949478:现在你有*另一个*原因!:-) (2认同)