Python 的 in (__contains__) 运算符返回一个布尔值,其值既不是 True 也不是 False
问题描述
正如所料,1 不包含在空元组中
As expected, 1 is not contained by the empty tuple
>>> 1 in ()
False
但是返回的False
值不等于False
>>> 1 in () == False
False
换个角度看,in
运算符返回一个 bool
,它既不是 True
也不是 False
:
Looking at it another way, the in
operator returns a bool
which is neither True
nor False
:
>>> type(1 in ())
<type 'bool'>
>>> 1 in () == True, 1 in () == False
(False, False)
但是,如果原始表达式被括号括起来,则正常行为会恢复
However, normal behaviour resumes if the original expression is parenthesized
>>> (1 in ()) == False
True
或者它的值存储在一个变量中
or its value is stored in a variable
>>> value = 1 in ()
>>> value == False
True
在 Python 2 和 Python 3 中都观察到了这种行为.
This behaviour is observed in both Python 2 and Python 3.
你能解释一下发生了什么吗?
Can you explain what is going on?
解决方案
您遇到了比较运算符链接;1 in () == False
not 表示 (1 in ()) == False
.
You are running into comparison operator chaining; 1 in () == False
does not mean (1 in ()) == False
.
相反,比较是链式的,表达式的真正含义是:
Rather, comparisons are chained and the expression really means:
(1 in ()) and (() == False)
因为 (1 in ())
已经为假,链式表达式的后半部分被完全忽略(因为 False and something_else
返回 False
无论 something_else
的值是什么).
Because (1 in ())
is already false, the second half of the chained expression is ignored altogether (since False and something_else
returns False
whatever the value of something_else
would be).
请参阅比较表达式文档:
比较可以任意链接,例如,x <y <= z
等价于 x <y 和 y <= z
,除了 y
只计算一次(但在这两种情况下,当 x
时根本不计算
被发现为假).z
; y
Comparisons can be chained arbitrarily, e.g.,
x < y <= z
is equivalent tox < y and y <= z
, except thaty
is evaluated only once (but in both casesz
is not evaluated at all whenx < y
is found to be false).
作为记录,<
, >
, ==
, >=
, <=
、!=
、is
、is not
、in
和 not in
都是比较运算符(不推荐使用的 <>
也是如此).
For the record, <
, >
, ==
, >=
, <=
, !=
, is
, is not
, in
and not in
are all comparison operators (as is the deprecated <>
).
一般来说,不要与布尔值进行比较;只需测试表达式本身.如果您有 需要针对布尔文字进行测试,至少使用括号和 is
运算符、True
和 False
是单例,就像 None
:
In general, don't compare against booleans; just test the expression itself. If you have to test against a boolean literal, at least use parenthesis and the is
operator, True
and False
are singletons, just like None
:
>>> (1 in ()) is False
True
当涉及整数时,这会变得更加混乱.Python bool
类型是 int
1 的子类.因此,False == 0
为真,True == 1
也是如此.因此,您可以想象创建看起来很正常的链式操作:
This gets more confusing still when integers are involved. The Python bool
type is a subclass of int
1. As such, False == 0
is true, as is True == 1
. You therefor can conceivably create chained operations that almost look sane:
3 > 1 == True
是真的,因为 3 >1
和 1 == True
都是真的.但表达式:
is true because 3 > 1
and 1 == True
are both true. But the expression:
3 > 2 == True
是假的,因为 2 == True
是假的.
is false, because 2 == True
is false.
1 bool
由于历史原因是 int
的子类;Python 并不总是像 C 那样具有 bool
类型和具有布尔含义的重载整数.将 bool
设为子类可以让旧代码继续工作.
1 bool
is a subclass of int
for historic reasons; Python didn't always have a bool
type and overloaded integers with boolean meaning just like C does. Making bool
a subclass kept older code working.
相关文章