【问题标题】:Python things which are neither True nor FalsePython 的东西既不是真也不是假
【发布时间】:2009-10-18 12:09:00
【问题描述】:

我刚刚发现了这个:

a = (None,)
print (a is True)
print (a is False)
print (a == True)
print (a == False)
print (a == None)
print (a is None)
if a : print "hello"
if not a : print "goodbye"

产生:

False
False
False
False
False
False
hello

所以 a 既不是,也不等于 True 或 False,但在 if 语句中充当 True。

为什么?

更新:

实际上,我刚刚意识到这并不像我想象的那样晦涩难懂。对于 a=2,我也得到相同的结果(虽然对于 a=0 或 a=1 不是,它们分别被认为等于 False 和 True)

【问题讨论】:

标签: python boolean


【解决方案1】:

我发现这里几乎所有的解释都无济于事,所以这里再试一次:

这里的混淆是因为“is”、“==”和“if”是三个不同的东西。

  • "is" 测试身份,也就是说,如果它是同一个对象。在这种情况下显然不是这样。
  • "==" 测试值是否相等,显然唯一具有 True 和 False 值的内置对象是对象 True 和 False(任何数字类型的数字 0 和 1 除外)。李>

重要的部分来了:

  • 'if' 测试布尔值。这意味着无论你给它什么表达式,它都会被转换为 True 或 False。你可以用 bool() 做同样的事情。并且 bool((None,)) 将返回 True。将评估为 False 的内容列在文档中(此处由其他人链接)

现在也许这只是在我的脑海中更加清晰,但至少我尝试过。 :)

【讨论】:

    【解决方案2】:

    a 是一个成员元组,其计算结果为 Trueis 测试对象的身份,因此,您在所有这些测试中得到 False== 测试对象的相等性,因此,您再次得到 False

    if 语句中,__bool__(或__nonzero__)用于评估对象,对于非空元组,它应该返回True,因此你得到True。希望能回答你的问题。

    编辑TrueFalse分别等于10的原因是因为bool类型实现为int类型的子类。

    【讨论】:

    【解决方案3】:

    python 中的东西不必是TrueFalse 之一。

    当它们用作 if/while 循环的文本表达式时,它们将被转换为布尔值。您不能使用is== 来测试它们的评估结果。你用bool( thing )

    >>> a = (None,)
    >>> bool(a)
    True
    

    另请注意:

    >>> 10 == True
    False
    >>> 10 is True
    False
    >>> bool(10)
    True
    

    【讨论】:

      【解决方案4】:

      TL;DR:

      if== 是完全不同的操作。 if 检查变量的真值,而 == 比较两个变量。 is 也会比较两个变量,但它会比较两个变量是否引用同一个对象。

      因此,将变量与TrueFalseNone 进行比较以检查其真值是没有意义的。

      if 用于变量时会发生什么?

      在 Python 中,像 if 这样的检查会隐式获取参数的 bool。所以

      if something:
      

      将(在后台)执行如下:

      if bool(something):
      

      请注意,您永远不应该在代码中使用后者,因为它被认为不那么 Python 并且速度较慢(因为 Python 使用了两个 bools:bool(bool(something)))。 始终使用if something

      如果您对 CPython 3.6 如何评估它感兴趣:

      请注意,CPython 在这里并不完全使用hasattr。它会检查xtype 是否实现了该方法,但没有通过__getattribute__ 方法(hasattr 会使用该方法)。

      在 Python2 中,该方法被称为 __nonzero__ 而不是 __bool__

      使用==比较变量时会发生什么?

      == 将检查是否相等(通常也称为“值相等”)。但是,这种相等性检查不会强制操作数(与其他编程语言不同)。 Python 中的值相等是显式实现的。所以你可以这样做:

      >>> 1 == True  # because bool subclasses int, True is equal to 1 (and False to 0)
      True
      
      >>> 1.0 == True  # because float implements __eq__ with int
      True
      
      >>> 1+1j == True  # because complex implements __eq__ with int
      True
      

      但是,如果两个操作数都没有实现比较,== 将默认为引用比较 (is)。这就是为什么:

      >>> (None, ) == True
      False
      

      因为tuple 不“支持”与int 相等,反之亦然。请注意,即使将列表与元组进行比较也是“不支持的”:

      >>> [None] == (None, )
      False
      

      如果您有兴趣,这就是 CPython (3.6) 如何实现相等(橙色箭头表示操作是否返回 NotImplemented 常量):

      这只是大致正确,因为 CPython 还会在调用(如果存在)或跳过(如果它不存在)。

      请注意,Python2 中的行为明显更长(至少在方法返回 NotImplemented 的情况下)并且 Python 2 也支持 __cmp__

      使用is比较变量时会发生什么?

      is 通常称为引用相等比较运算符。如果两个变量都引用完全相同的对象,它只会返回True。通常,具有相同值的变量仍然可以引用不同的对象:

      >>> 1 is 1.  # same value, different types
      False
      
      >>> a = 500
      >>> a is 500  # same value, same type, different instances
      False
      

      请注意,CPython 使用缓存值,因此有时“应该”是不同实例的变量实际上是同一个实例。这就是为什么我没有使用500 is 500(在同一行中具有相同值的文字总是相等)以及为什么我不能使用1 作为示例(因为CPython 重新使用值-5 到256)。

      但回到你的比较:is 比较引用,这意味着如果两个操作数具有相同的类型和值但它们必须是相同的引用是不够的。鉴于它们甚至没有相同的类型(您将 tupleboolNoneType 对象进行比较),is 不可能返回 True

      请注意,TrueFalseNone(还有 NotImplementedEllipsis)是 CPython 中的常量和单例。这不仅仅是在这些情况下的优化。

      【讨论】:

        【解决方案5】:

        (None,) 是一个包含元素的元组,它不是空的,因此在该上下文中不会评估为 False。

        【讨论】:

          【解决方案6】:

          因为a=(None,) 是一个包含单个元素None 的元组

          a=None再试一次,你会看到不同的结果。

          也可以试试a=(),它是空元组。这有一个假的真值

          【讨论】:

            【解决方案7】:

            在 Python 中,每种类型都可以通过使用bool() 函数或__nonzero__ method 转换为bool

            例子:

            • 序列(列表、字符串...)为空时将转换为False
            • 整数在等于 0 时转换为 False
            • 您可以通过覆盖__nonzero__() 在自己的类中定义此行为。

            [编辑]

            在您的代码中,元组 (None,)if 语句中使用 bool() 进行转换。由于它不是空的,它的计算结果为True

            【讨论】:

              猜你喜欢
              • 2013-12-20
              • 2016-11-14
              • 2023-03-11
              • 1970-01-01
              • 2021-02-27
              • 2014-01-31
              • 1970-01-01
              • 1970-01-01
              • 2015-10-10
              相关资源
              最近更新 更多