mirror of https://github.com/python/peps
510 lines
38 KiB
HTML
510 lines
38 KiB
HTML
|
||
<!DOCTYPE html>
|
||
<html lang="en">
|
||
<head>
|
||
<meta charset="utf-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<meta name="color-scheme" content="light dark">
|
||
<title>PEP 285 – Adding a bool type | peps.python.org</title>
|
||
<link rel="shortcut icon" href="../_static/py.png">
|
||
<link rel="canonical" href="https://peps.python.org/pep-0285/">
|
||
<link rel="stylesheet" href="../_static/style.css" type="text/css">
|
||
<link rel="stylesheet" href="../_static/mq.css" type="text/css">
|
||
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" media="(prefers-color-scheme: light)" id="pyg-light">
|
||
<link rel="stylesheet" href="../_static/pygments_dark.css" type="text/css" media="(prefers-color-scheme: dark)" id="pyg-dark">
|
||
<link rel="alternate" type="application/rss+xml" title="Latest PEPs" href="https://peps.python.org/peps.rss">
|
||
<meta property="og:title" content='PEP 285 – Adding a bool type | peps.python.org'>
|
||
<meta property="og:type" content="website">
|
||
<meta property="og:url" content="https://peps.python.org/pep-0285/">
|
||
<meta property="og:site_name" content="Python Enhancement Proposals (PEPs)">
|
||
<meta property="og:image" content="https://peps.python.org/_static/og-image.png">
|
||
<meta property="og:image:alt" content="Python PEPs">
|
||
<meta property="og:image:width" content="200">
|
||
<meta property="og:image:height" content="200">
|
||
<meta name="description" content="Python Enhancement Proposals (PEPs)">
|
||
<meta name="theme-color" content="#3776ab">
|
||
</head>
|
||
<body>
|
||
|
||
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
|
||
<symbol id="svg-sun-half" viewBox="0 0 24 24" pointer-events="all">
|
||
<title>Following system colour scheme</title>
|
||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
|
||
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||
<circle cx="12" cy="12" r="9"></circle>
|
||
<path d="M12 3v18m0-12l4.65-4.65M12 14.3l7.37-7.37M12 19.6l8.85-8.85"></path>
|
||
</svg>
|
||
</symbol>
|
||
<symbol id="svg-moon" viewBox="0 0 24 24" pointer-events="all">
|
||
<title>Selected dark colour scheme</title>
|
||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
|
||
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
|
||
<path d="M12 3c.132 0 .263 0 .393 0a7.5 7.5 0 0 0 7.92 12.446a9 9 0 1 1 -8.313 -12.454z"></path>
|
||
</svg>
|
||
</symbol>
|
||
<symbol id="svg-sun" viewBox="0 0 24 24" pointer-events="all">
|
||
<title>Selected light colour scheme</title>
|
||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
|
||
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||
<circle cx="12" cy="12" r="5"></circle>
|
||
<line x1="12" y1="1" x2="12" y2="3"></line>
|
||
<line x1="12" y1="21" x2="12" y2="23"></line>
|
||
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
|
||
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
|
||
<line x1="1" y1="12" x2="3" y2="12"></line>
|
||
<line x1="21" y1="12" x2="23" y2="12"></line>
|
||
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
|
||
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
|
||
</svg>
|
||
</symbol>
|
||
</svg>
|
||
<script>
|
||
|
||
document.documentElement.dataset.colour_scheme = localStorage.getItem("colour_scheme") || "auto"
|
||
</script>
|
||
<section id="pep-page-section">
|
||
<header>
|
||
<h1>Python Enhancement Proposals</h1>
|
||
<ul class="breadcrumbs">
|
||
<li><a href="https://www.python.org/" title="The Python Programming Language">Python</a> » </li>
|
||
<li><a href="../pep-0000/">PEP Index</a> » </li>
|
||
<li>PEP 285</li>
|
||
</ul>
|
||
<button id="colour-scheme-cycler" onClick="setColourScheme(nextColourScheme())">
|
||
<svg aria-hidden="true" class="colour-scheme-icon-when-auto"><use href="#svg-sun-half"></use></svg>
|
||
<svg aria-hidden="true" class="colour-scheme-icon-when-dark"><use href="#svg-moon"></use></svg>
|
||
<svg aria-hidden="true" class="colour-scheme-icon-when-light"><use href="#svg-sun"></use></svg>
|
||
<span class="visually-hidden">Toggle light / dark / auto colour theme</span>
|
||
</button>
|
||
</header>
|
||
<article>
|
||
<section id="pep-content">
|
||
<h1 class="page-title">PEP 285 – Adding a bool type</h1>
|
||
<dl class="rfc2822 field-list simple">
|
||
<dt class="field-odd">Author<span class="colon">:</span></dt>
|
||
<dd class="field-odd">Guido van Rossum <guido at python.org></dd>
|
||
<dt class="field-even">Status<span class="colon">:</span></dt>
|
||
<dd class="field-even"><abbr title="Accepted and implementation complete, or no longer active">Final</abbr></dd>
|
||
<dt class="field-odd">Type<span class="colon">:</span></dt>
|
||
<dd class="field-odd"><abbr title="Normative PEP with a new feature for Python, implementation change for CPython or interoperability standard for the ecosystem">Standards Track</abbr></dd>
|
||
<dt class="field-even">Created<span class="colon">:</span></dt>
|
||
<dd class="field-even">08-Mar-2002</dd>
|
||
<dt class="field-odd">Python-Version<span class="colon">:</span></dt>
|
||
<dd class="field-odd">2.3</dd>
|
||
<dt class="field-even">Post-History<span class="colon">:</span></dt>
|
||
<dd class="field-even">08-Mar-2002, 30-Mar-2002, 03-Apr-2002</dd>
|
||
</dl>
|
||
<hr class="docutils" />
|
||
<section id="contents">
|
||
<details><summary>Table of Contents</summary><ul class="simple">
|
||
<li><a class="reference internal" href="#abstract">Abstract</a></li>
|
||
<li><a class="reference internal" href="#review">Review</a></li>
|
||
<li><a class="reference internal" href="#rationale">Rationale</a></li>
|
||
<li><a class="reference internal" href="#specification">Specification</a></li>
|
||
<li><a class="reference internal" href="#c-api">C API</a></li>
|
||
<li><a class="reference internal" href="#clarification">Clarification</a></li>
|
||
<li><a class="reference internal" href="#compatibility">Compatibility</a></li>
|
||
<li><a class="reference internal" href="#resolved-issues">Resolved Issues</a></li>
|
||
<li><a class="reference internal" href="#implementation">Implementation</a></li>
|
||
<li><a class="reference internal" href="#copyright">Copyright</a></li>
|
||
</ul>
|
||
</details></section>
|
||
<section id="abstract">
|
||
<h2><a class="toc-backref" href="#abstract" role="doc-backlink">Abstract</a></h2>
|
||
<p>This PEP proposes the introduction of a new built-in type, bool,
|
||
with two constants, <code class="docutils literal notranslate"><span class="pre">False</span></code> and <code class="docutils literal notranslate"><span class="pre">True</span></code>. The bool type would be a
|
||
straightforward subtype (in C) of the int type, and the values
|
||
<code class="docutils literal notranslate"><span class="pre">False</span></code> and <code class="docutils literal notranslate"><span class="pre">True</span></code> would behave like 0 and 1 in most respects (for
|
||
example, <code class="docutils literal notranslate"><span class="pre">False==0</span></code> and <code class="docutils literal notranslate"><span class="pre">True==1</span></code> would be true) except <code class="docutils literal notranslate"><span class="pre">repr()</span></code> and
|
||
<code class="docutils literal notranslate"><span class="pre">str()</span></code>. All built-in operations that conceptually return a Boolean
|
||
result will be changed to return <code class="docutils literal notranslate"><span class="pre">False</span></code> or <code class="docutils literal notranslate"><span class="pre">True</span></code> instead of 0 or 1;
|
||
for example, comparisons, the “not” operator, and predicates like
|
||
<code class="docutils literal notranslate"><span class="pre">isinstance()</span></code>.</p>
|
||
</section>
|
||
<section id="review">
|
||
<h2><a class="toc-backref" href="#review" role="doc-backlink">Review</a></h2>
|
||
<p>I’ve collected enough feedback to last me a lifetime, so I declare
|
||
the review period officially OVER. I had Chinese food today; my
|
||
fortune cookie said “Strong and bitter words indicate a weak
|
||
cause.” It reminded me of some of the posts against this
|
||
PEP… :-)</p>
|
||
<p>Anyway, here are my BDFL pronouncements. (Executive summary: I’m
|
||
not changing a thing; all variants are rejected.)</p>
|
||
<ol class="arabic">
|
||
<li>Should this PEP be accepted?<p>=> Yes.</p>
|
||
<p>There have been many arguments against the PEP. Many of them
|
||
were based on misunderstandings. I’ve tried to clarify some of
|
||
the most common misunderstandings below in the main text of the
|
||
PEP. The only issue that weighs at all for me is the tendency
|
||
of newbies to write “if x == True” where “if x” would suffice.
|
||
More about that below too. I think this is not a sufficient
|
||
reason to reject the PEP.</p>
|
||
</li>
|
||
<li>Should <code class="docutils literal notranslate"><span class="pre">str(True)</span></code> return “True” or “1”? “1” might reduce
|
||
backwards compatibility problems, but looks strange.
|
||
(<code class="docutils literal notranslate"><span class="pre">repr(True)</span></code> would always return “True”.)<p>=> “True”.</p>
|
||
<p>Almost all reviewers agree with this.</p>
|
||
</li>
|
||
<li>Should the constants be called ‘True’ and ‘False’ (similar to
|
||
None) or ‘true’ and ‘false’ (as in C++, Java and C99)?<p>=> True and False.</p>
|
||
<p>Most reviewers agree that consistency within Python is more
|
||
important than consistency with other languages.</p>
|
||
</li>
|
||
<li>Should we strive to eliminate non-Boolean operations on bools
|
||
in the future, through suitable warnings, so that for example
|
||
True+1 would eventually (in Python 3000) be illegal?<p>=> No.</p>
|
||
<p>There’s a small but vocal minority that would prefer to see
|
||
“textbook” bools that don’t support arithmetic operations at
|
||
all, but most reviewers agree with me that bools should always
|
||
allow arithmetic operations.</p>
|
||
</li>
|
||
<li>Should <code class="docutils literal notranslate"><span class="pre">operator.truth(x)</span></code> return an int or a bool?<p>=> bool.</p>
|
||
<p>Tim Peters believes it should return an int, but almost all
|
||
other reviewers agree that it should return a bool. My
|
||
rationale: <code class="docutils literal notranslate"><span class="pre">operator.truth()</span></code> exists to force a Boolean context
|
||
on its argument (it calls the C API <code class="docutils literal notranslate"><span class="pre">PyObject_IsTrue())</span></code>.
|
||
Whether the outcome is reported as int or bool is secondary; if
|
||
bool exists there’s no reason not to use it. (Under the PEP,
|
||
<code class="docutils literal notranslate"><span class="pre">operator.truth()</span></code> now becomes an alias for <code class="docutils literal notranslate"><span class="pre">bool()</span></code>; that’s fine.)</p>
|
||
</li>
|
||
<li>Should bool inherit from int?<p>=> Yes.</p>
|
||
<p>In an ideal world, bool might be better implemented as a
|
||
separate integer type that knows how to perform mixed-mode
|
||
arithmetic. However, inheriting bool from int eases the
|
||
implementation enormously (in part since all C code that calls
|
||
<code class="docutils literal notranslate"><span class="pre">PyInt_Check()</span></code> will continue to work – this returns true for
|
||
subclasses of int). Also, I believe this is right in terms of
|
||
substitutability: code that requires an int can be fed a bool
|
||
and it will behave the same as 0 or 1. Code that requires a
|
||
bool may not work when it is given an int; for example, 3 & 4
|
||
is 0, but both 3 and 4 are true when considered as truth
|
||
values.</p>
|
||
</li>
|
||
<li>Should the name ‘bool’ be changed?<p>=> No.</p>
|
||
<p>Some reviewers have argued for boolean instead of bool, because
|
||
this would be easier to understand (novices may have heard of
|
||
Boolean algebra but may not make the connection with bool) or
|
||
because they hate abbreviations. My take: Python uses
|
||
abbreviations judiciously (like ‘def’, ‘int’, ‘dict’) and I
|
||
don’t think these are a burden to understanding. To a newbie,
|
||
it doesn’t matter whether it’s called a waffle or a bool; it’s
|
||
a new word, and they learn quickly what it means.</p>
|
||
<p>One reviewer has argued to make the name ‘truth’. I find this
|
||
an unattractive name, and would actually prefer to reserve this
|
||
term (in documentation) for the more abstract concept of truth
|
||
values that already exists in Python. For example: “when a
|
||
container is interpreted as a truth value, an empty container
|
||
is considered false and a non-empty one is considered true.”</p>
|
||
</li>
|
||
<li>Should we strive to require that Boolean operations (like “if”,
|
||
“and”, “not”) have a bool as an argument in the future, so that
|
||
for example “if []:” would become illegal and would have to be
|
||
written as “if bool([]):” ???<p>=> No!!!</p>
|
||
<p>Some people believe that this is how a language with a textbook
|
||
Boolean type should behave. Because it was brought up, others
|
||
have worried that I might agree with this position. Let me
|
||
make my position on this quite clear. This is not part of the
|
||
PEP’s motivation and I don’t intend to make this change. (See
|
||
also the section “Clarification” below.)</p>
|
||
</li>
|
||
</ol>
|
||
</section>
|
||
<section id="rationale">
|
||
<h2><a class="toc-backref" href="#rationale" role="doc-backlink">Rationale</a></h2>
|
||
<p>Most languages eventually grow a Boolean type; even C99 (the new
|
||
and improved C standard, not yet widely adopted) has one.</p>
|
||
<p>Many programmers apparently feel the need for a Boolean type; most
|
||
Python documentation contains a bit of an apology for the absence
|
||
of a Boolean type. I’ve seen lots of modules that defined
|
||
constants “False=0” and “True=1” (or similar) at the top and used
|
||
those. The problem with this is that everybody does it
|
||
differently. For example, should you use “FALSE”, “false”,
|
||
“False”, “F” or even “f”? And should false be the value zero or
|
||
None, or perhaps a truth value of a different type that will print
|
||
as “true” or “false”? Adding a standard bool type to the language
|
||
resolves those issues.</p>
|
||
<p>Some external libraries (like databases and RPC packages) need to
|
||
be able to distinguish between Boolean and integral values, and
|
||
while it’s usually possible to craft a solution, it would be
|
||
easier if the language offered a standard Boolean type. This also
|
||
applies to Jython: some Java classes have separately overloaded
|
||
methods or constructors for int and boolean arguments. The bool
|
||
type can be used to select the boolean variant. (The same is
|
||
apparently the case for some COM interfaces.)</p>
|
||
<p>The standard bool type can also serve as a way to force a value to
|
||
be interpreted as a Boolean, which can be used to normalize
|
||
Boolean values. When a Boolean value needs to be normalized to
|
||
one of two values, <code class="docutils literal notranslate"><span class="pre">bool(x)</span></code> is much clearer than “not not x” and
|
||
much more concise than</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">if</span> <span class="n">x</span><span class="p">:</span>
|
||
<span class="k">return</span> <span class="mi">1</span>
|
||
<span class="k">else</span><span class="p">:</span>
|
||
<span class="k">return</span> <span class="mi">0</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>Here are some arguments derived from teaching Python. When
|
||
showing people comparison operators etc. in the interactive shell,
|
||
I think this is a bit ugly:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">a</span> <span class="o">=</span> <span class="mi">13</span>
|
||
<span class="gp">>>> </span><span class="n">b</span> <span class="o">=</span> <span class="mi">12</span>
|
||
<span class="gp">>>> </span><span class="n">a</span> <span class="o">></span> <span class="n">b</span>
|
||
<span class="go">1</span>
|
||
<span class="gp">>>></span>
|
||
</pre></div>
|
||
</div>
|
||
<p>If this was:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">a</span> <span class="o">></span> <span class="n">b</span>
|
||
<span class="go">True</span>
|
||
<span class="gp">>>></span>
|
||
</pre></div>
|
||
</div>
|
||
<p>it would require a millisecond less thinking each time a 0 or 1
|
||
was printed.</p>
|
||
<p>There’s also the issue (which I’ve seen baffling even experienced
|
||
Pythonistas who had been away from the language for a while) that
|
||
if you see:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">cmp</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">)</span>
|
||
<span class="go">1</span>
|
||
<span class="gp">>>> </span><span class="n">cmp</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">a</span><span class="p">)</span>
|
||
<span class="go">0</span>
|
||
<span class="gp">>>></span>
|
||
</pre></div>
|
||
</div>
|
||
<p>you might be tempted to believe that <code class="docutils literal notranslate"><span class="pre">cmp()</span></code> also returned a truth
|
||
value, whereas in reality it can return three different values
|
||
<code class="docutils literal notranslate"><span class="pre">(-1,</span> <span class="pre">0,</span> <span class="pre">1)</span></code>. If ints were not (normally) used to represent
|
||
Booleans results, this would stand out much more clearly as
|
||
something completely different.</p>
|
||
</section>
|
||
<section id="specification">
|
||
<h2><a class="toc-backref" href="#specification" role="doc-backlink">Specification</a></h2>
|
||
<p>The following Python code specifies most of the properties of the
|
||
new type:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">bool</span><span class="p">(</span><span class="nb">int</span><span class="p">):</span>
|
||
|
||
<span class="k">def</span> <span class="fm">__new__</span><span class="p">(</span><span class="bp">cls</span><span class="p">,</span> <span class="n">val</span><span class="o">=</span><span class="mi">0</span><span class="p">):</span>
|
||
<span class="c1"># This constructor always returns an existing instance</span>
|
||
<span class="k">if</span> <span class="n">val</span><span class="p">:</span>
|
||
<span class="k">return</span> <span class="kc">True</span>
|
||
<span class="k">else</span><span class="p">:</span>
|
||
<span class="k">return</span> <span class="kc">False</span>
|
||
|
||
<span class="k">def</span> <span class="fm">__repr__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||
<span class="k">if</span> <span class="bp">self</span><span class="p">:</span>
|
||
<span class="k">return</span> <span class="s2">"True"</span>
|
||
<span class="k">else</span><span class="p">:</span>
|
||
<span class="k">return</span> <span class="s2">"False"</span>
|
||
|
||
<span class="fm">__str__</span> <span class="o">=</span> <span class="fm">__repr__</span>
|
||
|
||
<span class="k">def</span> <span class="fm">__and__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">other</span><span class="p">):</span>
|
||
<span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">other</span><span class="p">,</span> <span class="nb">bool</span><span class="p">):</span>
|
||
<span class="k">return</span> <span class="nb">bool</span><span class="p">(</span><span class="nb">int</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">&</span> <span class="nb">int</span><span class="p">(</span><span class="n">other</span><span class="p">))</span>
|
||
<span class="k">else</span><span class="p">:</span>
|
||
<span class="k">return</span> <span class="nb">int</span><span class="o">.</span><span class="fm">__and__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">other</span><span class="p">)</span>
|
||
|
||
<span class="fm">__rand__</span> <span class="o">=</span> <span class="fm">__and__</span>
|
||
|
||
<span class="k">def</span> <span class="fm">__or__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">other</span><span class="p">):</span>
|
||
<span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">other</span><span class="p">,</span> <span class="nb">bool</span><span class="p">):</span>
|
||
<span class="k">return</span> <span class="nb">bool</span><span class="p">(</span><span class="nb">int</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">|</span> <span class="nb">int</span><span class="p">(</span><span class="n">other</span><span class="p">))</span>
|
||
<span class="k">else</span><span class="p">:</span>
|
||
<span class="k">return</span> <span class="nb">int</span><span class="o">.</span><span class="fm">__or__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">other</span><span class="p">)</span>
|
||
|
||
<span class="fm">__ror__</span> <span class="o">=</span> <span class="fm">__or__</span>
|
||
|
||
<span class="k">def</span> <span class="fm">__xor__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">other</span><span class="p">):</span>
|
||
<span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">other</span><span class="p">,</span> <span class="nb">bool</span><span class="p">):</span>
|
||
<span class="k">return</span> <span class="nb">bool</span><span class="p">(</span><span class="nb">int</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">^</span> <span class="nb">int</span><span class="p">(</span><span class="n">other</span><span class="p">))</span>
|
||
<span class="k">else</span><span class="p">:</span>
|
||
<span class="k">return</span> <span class="nb">int</span><span class="o">.</span><span class="fm">__xor__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">other</span><span class="p">)</span>
|
||
|
||
<span class="fm">__rxor__</span> <span class="o">=</span> <span class="fm">__xor__</span>
|
||
|
||
<span class="c1"># Bootstrap truth values through sheer willpower</span>
|
||
<span class="kc">False</span> <span class="o">=</span> <span class="nb">int</span><span class="o">.</span><span class="fm">__new__</span><span class="p">(</span><span class="nb">bool</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span>
|
||
<span class="kc">True</span> <span class="o">=</span> <span class="nb">int</span><span class="o">.</span><span class="fm">__new__</span><span class="p">(</span><span class="nb">bool</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>The values <code class="docutils literal notranslate"><span class="pre">False</span></code> and <code class="docutils literal notranslate"><span class="pre">True</span></code> will be singletons, like None. Because
|
||
the type has two values, perhaps these should be called
|
||
“doubletons”? The real implementation will not allow other
|
||
instances of bool to be created.</p>
|
||
<p><code class="docutils literal notranslate"><span class="pre">True</span></code> and <code class="docutils literal notranslate"><span class="pre">False</span></code> will properly round-trip through pickling and
|
||
marshalling; for example <code class="docutils literal notranslate"><span class="pre">pickle.loads(pickle.dumps(True))</span></code> will
|
||
return <code class="docutils literal notranslate"><span class="pre">True</span></code>, and so will <code class="docutils literal notranslate"><span class="pre">marshal.loads(marshal.dumps(True))</span></code>.</p>
|
||
<p>All built-in operations that are defined to return a Boolean
|
||
result will be changed to return <code class="docutils literal notranslate"><span class="pre">False</span></code> or <code class="docutils literal notranslate"><span class="pre">True</span></code> instead of 0 or 1.
|
||
In particular, this affects comparisons (<code class="docutils literal notranslate"><span class="pre"><</span></code>, <code class="docutils literal notranslate"><span class="pre"><=</span></code>, <code class="docutils literal notranslate"><span class="pre">==</span></code>, <code class="docutils literal notranslate"><span class="pre">!=</span></code>,
|
||
<code class="docutils literal notranslate"><span class="pre">></span></code>, <code class="docutils literal notranslate"><span class="pre">>=</span></code>, is, is not, in, not in), the unary operator ‘not’, the built-in
|
||
functions <code class="docutils literal notranslate"><span class="pre">callable()</span></code>, <code class="docutils literal notranslate"><span class="pre">hasattr()</span></code>, <code class="docutils literal notranslate"><span class="pre">isinstance()</span></code> and <code class="docutils literal notranslate"><span class="pre">issubclass()</span></code>,
|
||
the dict method <code class="docutils literal notranslate"><span class="pre">has_key()</span></code>, the string and unicode methods
|
||
<code class="docutils literal notranslate"><span class="pre">endswith()</span></code>, <code class="docutils literal notranslate"><span class="pre">isalnum()</span></code>, <code class="docutils literal notranslate"><span class="pre">isalpha()</span></code>, <code class="docutils literal notranslate"><span class="pre">isdigit()</span></code>, <code class="docutils literal notranslate"><span class="pre">islower()</span></code>, <code class="docutils literal notranslate"><span class="pre">isspace()</span></code>,
|
||
<code class="docutils literal notranslate"><span class="pre">istitle()</span></code>, <code class="docutils literal notranslate"><span class="pre">isupper()</span></code>, and <code class="docutils literal notranslate"><span class="pre">startswith()</span></code>, the unicode methods
|
||
<code class="docutils literal notranslate"><span class="pre">isdecimal()</span></code> and <code class="docutils literal notranslate"><span class="pre">isnumeric()</span></code>, and the ‘closed’ attribute of file
|
||
objects. The predicates in the operator module are also changed
|
||
to return a bool, including <code class="docutils literal notranslate"><span class="pre">operator.truth()</span></code>.</p>
|
||
<p>Because bool inherits from int, True+1 is valid and equals 2, and
|
||
so on. This is important for backwards compatibility: because
|
||
comparisons and so on currently return integer values, there’s no
|
||
way of telling what uses existing applications make of these
|
||
values.</p>
|
||
<p>It is expected that over time, the standard library will be
|
||
updated to use <code class="docutils literal notranslate"><span class="pre">False</span></code> and <code class="docutils literal notranslate"><span class="pre">True</span></code> when appropriate (but not to require
|
||
a bool argument type where previous an int was allowed). This
|
||
change should not pose additional problems and is not specified in
|
||
detail by this PEP.</p>
|
||
</section>
|
||
<section id="c-api">
|
||
<h2><a class="toc-backref" href="#c-api" role="doc-backlink">C API</a></h2>
|
||
<p>The header file “boolobject.h” defines the C API for the bool
|
||
type. It is included by “Python.h” so there is no need to include
|
||
it directly.</p>
|
||
<p>The existing names <code class="docutils literal notranslate"><span class="pre">Py_False</span></code> and <code class="docutils literal notranslate"><span class="pre">Py_True</span></code> reference the unique bool
|
||
objects <code class="docutils literal notranslate"><span class="pre">False</span></code> and <code class="docutils literal notranslate"><span class="pre">True</span></code> (previously these referenced static int
|
||
objects with values 0 and 1, which were not unique amongst int
|
||
values).</p>
|
||
<p>A new API, <code class="docutils literal notranslate"><span class="pre">PyObject</span> <span class="pre">*PyBool_FromLong(long)</span></code>, takes a C long int
|
||
argument and returns a new reference to either <code class="docutils literal notranslate"><span class="pre">Py_False</span></code> (when the
|
||
argument is zero) or <code class="docutils literal notranslate"><span class="pre">Py_True</span></code> (when it is nonzero).</p>
|
||
<p>To check whether an object is a bool, the macro <code class="docutils literal notranslate"><span class="pre">PyBool_Check()</span></code> can
|
||
be used.</p>
|
||
<p>The type of bool instances is <code class="docutils literal notranslate"><span class="pre">PyBoolObject</span> <span class="pre">*</span></code>.</p>
|
||
<p>The bool type object is available as PyBool_Type.</p>
|
||
</section>
|
||
<section id="clarification">
|
||
<h2><a class="toc-backref" href="#clarification" role="doc-backlink">Clarification</a></h2>
|
||
<p>This PEP does <strong>not</strong> change the fact that almost all object types
|
||
can be used as truth values. For example, when used in an if
|
||
statement, an empty list is false and a non-empty one is true;
|
||
this does not change and there is no plan to ever change this.</p>
|
||
<p>The only thing that changes is the preferred values to represent
|
||
truth values when returned or assigned explicitly. Previously,
|
||
these preferred truth values were 0 and 1; the PEP changes the
|
||
preferred values to <code class="docutils literal notranslate"><span class="pre">False</span></code> and <code class="docutils literal notranslate"><span class="pre">True</span></code>, and changes built-in
|
||
operations to return these preferred values.</p>
|
||
</section>
|
||
<section id="compatibility">
|
||
<h2><a class="toc-backref" href="#compatibility" role="doc-backlink">Compatibility</a></h2>
|
||
<p>Because of backwards compatibility, the bool type lacks many
|
||
properties that some would like to see. For example, arithmetic
|
||
operations with one or two bool arguments is allowed, treating
|
||
<code class="docutils literal notranslate"><span class="pre">False</span></code> as 0 and <code class="docutils literal notranslate"><span class="pre">True</span></code> as 1. Also, a bool may be used as a sequence
|
||
index.</p>
|
||
<p>I don’t see this as a problem, and I don’t want evolve the
|
||
language in this direction either. I don’t believe that a
|
||
stricter interpretation of “Booleanness” makes the language any
|
||
clearer.</p>
|
||
<p>Another consequence of the compatibility requirement is that the
|
||
expression “True and 6” has the value 6, and similarly the
|
||
expression “False or None” has the value None. The “and” and “or”
|
||
operators are usefully defined to return the first argument that
|
||
determines the outcome, and this won’t change; in particular, they
|
||
don’t force the outcome to be a bool. Of course, if both
|
||
arguments are bools, the outcome is always a bool. It can also
|
||
easily be coerced into being a bool by writing for example “bool(x
|
||
and y)”.</p>
|
||
</section>
|
||
<section id="resolved-issues">
|
||
<h2><a class="toc-backref" href="#resolved-issues" role="doc-backlink">Resolved Issues</a></h2>
|
||
<p>(See also the Review section above.)</p>
|
||
<ul>
|
||
<li>Because the <code class="docutils literal notranslate"><span class="pre">repr()</span></code> or <code class="docutils literal notranslate"><span class="pre">str()</span></code> of a bool value is different from an
|
||
int value, some code (for example doctest-based unit tests, and
|
||
possibly database code that relies on things like “%s” % truth)
|
||
may fail. It is easy to work around this (without explicitly
|
||
referencing the bool type), and it is expected that this only
|
||
affects a very small amount of code that can easily be fixed.</li>
|
||
<li>Other languages (C99, C++, Java) name the constants “false” and
|
||
“true”, in all lowercase. For Python, I prefer to stick with
|
||
the example set by the existing built-in constants, which all
|
||
use CapitalizedWords: <code class="docutils literal notranslate"><span class="pre">None</span></code>, <code class="docutils literal notranslate"><span class="pre">Ellipsis</span></code>, <code class="docutils literal notranslate"><span class="pre">NotImplemented</span></code> (as well as
|
||
all built-in exceptions). Python’s built-in namespace uses all
|
||
lowercase for functions and types only.</li>
|
||
<li>It has been suggested that, in order to satisfy user
|
||
expectations, for every x that is considered true in a Boolean
|
||
context, the expression <code class="docutils literal notranslate"><span class="pre">x</span> <span class="pre">==</span> <span class="pre">True</span></code> should be true, and likewise
|
||
if x is considered false, <code class="docutils literal notranslate"><span class="pre">x</span> <span class="pre">==</span> <span class="pre">False</span></code> should be true. In
|
||
particular newbies who have only just learned about Boolean
|
||
variables are likely to write<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">if</span> <span class="n">x</span> <span class="o">==</span> <span class="kc">True</span><span class="p">:</span> <span class="o">...</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>instead of the correct form,</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">if</span> <span class="n">x</span><span class="p">:</span> <span class="o">...</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>There seem to be strong psychological and linguistic reasons why
|
||
many people are at first uncomfortable with the latter form, but
|
||
I believe that the solution should be in education rather than
|
||
in crippling the language. After all, == is general seen as a
|
||
transitive operator, meaning that from <code class="docutils literal notranslate"><span class="pre">a==b</span></code> and <code class="docutils literal notranslate"><span class="pre">b==c</span></code> we can
|
||
deduce <code class="docutils literal notranslate"><span class="pre">a==c</span></code>. But if any comparison to <code class="docutils literal notranslate"><span class="pre">True</span></code> were to report
|
||
equality when the other operand was a true value of any type,
|
||
atrocities like <code class="docutils literal notranslate"><span class="pre">6==True==7</span></code> would hold true, from which one could
|
||
infer the falsehood <code class="docutils literal notranslate"><span class="pre">6==7</span></code>. That’s unacceptable. (In addition,
|
||
it would break backwards compatibility. But even if it didn’t,
|
||
I’d still be against this, for the stated reasons.)</p>
|
||
<p>Newbies should also be reminded that there’s never a reason to
|
||
write</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">if</span> <span class="nb">bool</span><span class="p">(</span><span class="n">x</span><span class="p">):</span> <span class="o">...</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>since the bool is implicit in the “if”. Explicit is <strong>not</strong>
|
||
better than implicit here, since the added verbiage impairs
|
||
readability and there’s no other interpretation possible. There
|
||
is, however, sometimes a reason to write</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">b</span> <span class="o">=</span> <span class="nb">bool</span><span class="p">(</span><span class="n">x</span><span class="p">)</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>This is useful when it is unattractive to keep a reference to an
|
||
arbitrary object x, or when normalization is required for some
|
||
other reason. It is also sometimes appropriate to write</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">i</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="nb">bool</span><span class="p">(</span><span class="n">x</span><span class="p">))</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>which converts the bool to an int with the value 0 or 1. This
|
||
conveys the intention to henceforth use the value as an int.</p>
|
||
</li>
|
||
</ul>
|
||
</section>
|
||
<section id="implementation">
|
||
<h2><a class="toc-backref" href="#implementation" role="doc-backlink">Implementation</a></h2>
|
||
<p>A complete implementation in C has been uploaded to the
|
||
SourceForge patch manager: <a class="reference external" href="https://bugs.python.org/issue528022">https://bugs.python.org/issue528022</a></p>
|
||
<p>This will soon be checked into CVS for python 2.3a0.</p>
|
||
</section>
|
||
<section id="copyright">
|
||
<h2><a class="toc-backref" href="#copyright" role="doc-backlink">Copyright</a></h2>
|
||
<p>This document has been placed in the public domain.</p>
|
||
</section>
|
||
</section>
|
||
<hr class="docutils" />
|
||
<p>Source: <a class="reference external" href="https://github.com/python/peps/blob/main/peps/pep-0285.rst">https://github.com/python/peps/blob/main/peps/pep-0285.rst</a></p>
|
||
<p>Last modified: <a class="reference external" href="https://github.com/python/peps/commits/main/peps/pep-0285.rst">2023-09-09 17:39:29 GMT</a></p>
|
||
|
||
</article>
|
||
<nav id="pep-sidebar">
|
||
<h2>Contents</h2>
|
||
<ul>
|
||
<li><a class="reference internal" href="#abstract">Abstract</a></li>
|
||
<li><a class="reference internal" href="#review">Review</a></li>
|
||
<li><a class="reference internal" href="#rationale">Rationale</a></li>
|
||
<li><a class="reference internal" href="#specification">Specification</a></li>
|
||
<li><a class="reference internal" href="#c-api">C API</a></li>
|
||
<li><a class="reference internal" href="#clarification">Clarification</a></li>
|
||
<li><a class="reference internal" href="#compatibility">Compatibility</a></li>
|
||
<li><a class="reference internal" href="#resolved-issues">Resolved Issues</a></li>
|
||
<li><a class="reference internal" href="#implementation">Implementation</a></li>
|
||
<li><a class="reference internal" href="#copyright">Copyright</a></li>
|
||
</ul>
|
||
|
||
<br>
|
||
<a id="source" href="https://github.com/python/peps/blob/main/peps/pep-0285.rst">Page Source (GitHub)</a>
|
||
</nav>
|
||
</section>
|
||
<script src="../_static/colour_scheme.js"></script>
|
||
<script src="../_static/wrap_tables.js"></script>
|
||
<script src="../_static/sticky_banner.js"></script>
|
||
</body>
|
||
</html> |