<p>建议不是永远不要使用</strong><code>True</code>、<code>False</code>或<code>None</code>。只是你不应该使用<code>if x == True</code>。</p>
<p><code>if x == True</code>是愚蠢的,因为<code>==</code>只是一个二进制运算符!它的返回值为<code>True</code>或<code>False</code>,这取决于它的参数是否相等。如果<code>condition</code>为真,则<code>if condition</code>将继续。因此,当您编写<code>if x == True</code>时,Python将首先计算<code>x == True</code>,如果<code>x</code>是<code>True</code>,否则将变成<code>True</code>,如果结果是真的,则继续。但是如果您希望<code>x</code>是<code>True</code>或<code>False</code>,为什么不直接使用<code>if x</code>!</p>
<p>同样,<code>x == False</code>通常可以被<code>not x</code>替换。</p>
<p>在某些情况下,您可能需要使用<code>x == True</code>。这是因为<code>if</code>语句条件是“在布尔上下文中求值”的,以查看它是否是“truthy”,而不是完全针对<code>True</code>进行测试。例如,非空字符串、列表和字典都被if语句视为truthy,也被视为非零数值,但它们都不等于<code>True</code>。所以,如果你想测试一个任意的值是否是<code>True</code>的值,而不仅仅是它是否真实,当你使用<code>if x == True</code>时。但我几乎看不到它的用处。如果你真的需要写这篇文章,那么添加一条评论是非常罕见的,这样未来的开发人员(可能包括你自己)就不会认为<code>== True</code>是多余的,然后删除它。</p>
<hr/>
<p>相反,使用<code>x is True</code>实际上更糟。决不能将<code>is</code>与基本的内置不可变类型(如布尔值(<code>True</code>,<code>False</code>)、数字和字符串一起使用。原因是,对于这些类型,我们关心的是<strong>值</strong>,而不是<strong>标识</strong>。<code>==</code>测试这些类型的值是否相同,而<code>is</code>始终测试标识。</p>
<p>测试标识而不是值是不好的,因为一个实现在理论上可以构造新的布尔值,而不是去寻找现有的布尔值,这会导致有两个具有相同值的<code>True</code>值,但它们存储在内存中的不同位置,并且具有不同的标识。在实践中,我非常确定Python解释器总是重用<code>True</code>和<code>False</code>,因此不会发生这种情况,但这确实是一个实现细节。这个问题总是让人们对字符串感到困惑,因为直接出现在程序源代码中的短字符串和文本字符串被Python回收,所以<code>'foo' is 'foo'</code>总是返回<code>True</code>。但是很容易用两种不同的方法构造同一个字符串,并让Python赋予它们不同的标识。注意以下事项:</p>
<pre><code>>>> stars1 = ''.join('*' for _ in xrange(100))
>>> stars2 = '*' * 100
>>> stars1 is stars2
False
>>> stars1 == stars2
True
</code></pre>
<p><strong>编辑:</strong>因此,Python在布尔上的相等性有点出乎意料(至少对我来说):</p>
<pre><code>>>> True is 1
False
>>> True == 1
True
>>> True == 2
False
>>> False is 0
False
>>> False == 0
True
>>> False == 0.0
True
</code></pre>
<p>正如<a href="http://docs.python.org/release/2.3.5/whatsnew/section-bool.html" rel="nofollow noreferrer">the notes when bools were introduced in Python 2.3.5</a>中所解释的,其基本原理是,使用整数1和0来表示真值和假值的旧行为是好的,但我们只希望对表示真值的数字使用更具描述性的名称。</p>
<p>实现这一点的一种方法是在内置代码中简单地包含<code>True = 1</code>和<code>False = 0</code>;然后1和True将无法区分(包括<code>is</code>)。但这也意味着返回<code>True</code>的函数将在交互式解释器中显示<code>1</code>,因此我们所做的是将<code>bool</code>创建为<code>int</code>的子类型。关于<code>bool</code>唯一不同的是<code>str</code>和<code>repr</code>;<code>bool</code>实例仍然具有与<code>int</code>实例相同的数据,并且仍然以相同的方式比较相等,因此<code>True == 1</code>。</p>
<p>因此,当<code>x</code>可能被某些代码设置为“True只是拼写1的另一种方式”时,使用<code>x is True</code>是错误的,因为有很多方法可以构造等于<code>True</code>但不具有相同标识的值:</p>
<pre><code>>>> a = 1L
>>> b = 1L
>>> c = 1
>>> d = 1.0
>>> a == True, b == True, c == True, d == True
(True, True, True, True)
>>> a is b, a is c, a is d, c is d
(False, False, False, False)
</code></pre>
<p>你错了se <code>x == True</code>当<code>x</code>可以是任意Python值时,您只想知道它是否是布尔值<code>True</code>。我们唯一确定的是,当您只想测试“真实性”时,最好使用<code>x</code>。谢天谢地,这通常是所有需要的,至少在我写的代码中!</p>
<p>更可靠的方法是<code>x == True and type(x) is bool</code>。但对于一个不太清楚的案子来说,这就太冗长了。通过执行显式类型检查,它看起来也不太像Python。。。但是,当您试图精确地测试<code>True</code>而不是truthy时,您所做的就是这样;duck类型的方法是接受truthy值,并允许任何用户定义的类声明自己是truthy的。</p>
<p>如果您正在处理这个非常精确的真理概念,其中您不仅不认为非空集合是真的,而且也不认为1是真的,那么只使用<code>x is True</code>可能是可以的,因为您大概知道<code>x</code>不是来自于认为1为真的代码。我不认为有任何纯python的方法可以产生另一个<code>True</code>,它位于不同的内存地址(尽管您可能可以从C中完成它),因此这不应该中断,尽管理论上是“错误的”事情。</p>
<p>我以前认为布尔人很简单!</p>
<p><strong>结束编辑</strong></p>
<hr/>
<p>然而,对于<code>None</code>,习惯用法是使用<code>if x is None</code>。在许多情况下,您可以使用<code>if not x</code>,因为<code>None</code>是<code>if</code>语句的“false”值。但是,如果您希望以相同的方式处理所有错误的值(零值数值类型、空集合和<code>None</code>),最好这样做。如果处理的值可能是其他值,也可能是指示“无值”的<code>None</code>(例如,当函数失败时返回<code>None</code>),那么最好使用<code>if x is None</code>,这样就不会在函数恰好返回空列表或数字0时意外假设函数失败。</p>
<p>我关于对不可变值类型使用<code>==</code>而不是<code>is</code>的参数建议您应该使用<code>if x == None</code>,而不是<code>if x is None</code>。然而,在<code>None</code>的情况下,Python确实显式地保证整个宇宙中只有一个<code>None</code>,并且普通的Python惯用代码使用<code>is</code>。</p>
<hr/>
<p>关于是返回<code>None</code>还是引发异常,这取决于上下文。</p>
<p>对于您的<code>get_attr</code>示例,我希望它引发异常,因为我将像<code>do_something_with(get_attr(file))</code>那样调用它。调用者通常的期望是,他们会得到属性值,让他们得到<code>None</code>,并假设是属性值,这比在找不到属性时忘记处理异常要危险得多。另外,返回<code>None</code>表示失败意味着<code>None</code>不是属性的有效值。在某些情况下,这可能是一个问题。</p>
<p>对于像<code>see_if_matching_file_exists</code>这样的虚函数,我们提供一个模式给它,它检查几个地方看是否有匹配,如果找到一个,它可以返回一个匹配,如果没有,它可以返回<code>None</code>。但是它也可以返回一个匹配列表;那么没有匹配只是空列表(这也是“false”;在这种情况下,我只需要使用<code>if x</code>来查看是否有任何东西回来。</p>
<p>因此,当在异常和<code>None</code>之间进行选择以指示失败时,必须确定<code>None</code>是否是预期的非失败值,然后查看调用函数的代码的预期值。如果“正常”的期望是返回一个有效值,并且只有偶尔调用方能够正常工作,无论是否返回有效值,那么您应该使用异常来指示失败。如果没有有效值是很常见的,那么调用者将期望处理这两个possi概率,然后可以使用<code>None</code>。</p>