【问题标题】:Python's in (__contains__) operator returns a bool whose value is neither True nor FalsePython 的 in (__contains__) 运算符返回一个布尔值,其值既不是 True 也不是 False
【发布时间】:2013-11-14 02:49:03
【问题描述】:

正如所料,1 不包含在空元组中

>>> 1 in ()
False

但返回的False 值不等于False

>>> 1 in () == False
False

换个角度看,in 运算符返回一个bool,它既不是True 也不是False

>>> type(1 in ())
<type 'bool'>
>>> 1 in () == True, 1 in () == False
(False, False)

但是,如果原始表达式被括号括起来,则正常行为会恢复

>>> (1 in ()) == False
True

或者它的值存储在一个变量中

>>> value = 1 in ()
>>> value == False
True

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

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

【问题讨论】:

    标签: python boolean membership comparison-operators


    【解决方案1】:

    您遇到了比较运算符链接; 1 in () == False 不是表示(1 in ()) == False

    相反,比较是链式的,表达式的真正含义是:

    (1 in ()) and (() == False)
    

    因为(1 in ()) 已经为假,链式表达式的后半部分将被完全忽略(因为False and something_else 返回False,无论something_else 的值是什么)。

    comparisons expressions documentation

    比较可以任意链接,例如,x &lt; y &lt;= z 等价于 x &lt; y and y &lt;= z,除了 y 只被评估一次(但在这两种情况下,z 根本不被评估,当 x &lt; y 被发现是假的)。

    为了记录,&lt;&gt;==&gt;=&lt;=!=isis notinnot in都是比较运算符(与已弃用的 &lt;&gt; 一样)。

    一般来说,不要与布尔值进行比较;只需测试表达式本身。如果您必须针对布尔文字进行测试,至少使用括号和is 运算符,TrueFalse 是单例,就像None

    >>> (1 in ()) is False
    True
    

    当涉及整数时,这会变得更加混乱。 Python bool 类型是 int1 的子类。因此,False == 0 是真的,True == 1 也是如此。因此,您可以想象创建看起来很正常的链式操作:

    3 > 1 == True
    

    是真的,因为3 &gt; 11 == True 都是真的。但表达式:

    3 > 2 == True
    

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

    1boolint 的子类,因为历史原因; Python 并不总是像 C 那样具有 bool 类型和具有布尔含义的重载整数。将bool 设为子类可使旧代码继续工作。

    【讨论】:

    • 谢谢,这很有道理。不会梦想与现实生活中的布尔表达式进行比较,但在试图向某人解释为什么不应该这样做时偶然发现了这种好奇心。
    • @user2949478:现在你有了另一个的理由! :-)
    • 这在我看来违反了最小惊讶原则。我可以看到像 a is b is None1 &lt; x &lt; 10 这样的表达式,但不能在 innot inisis not 之间混合,或者与(in)相等运算符混合。
    猜你喜欢
    • 2017-09-29
    • 1970-01-01
    • 2013-08-17
    • 1970-01-01
    • 2017-11-23
    • 2020-03-15
    • 2021-09-24
    • 1970-01-01
    相关资源
    最近更新 更多