reSTify PEP 285 (#366)

This commit is contained in:
Huang Huang 2017-09-13 07:27:12 +08:00 committed by Guido van Rossum
parent 27d218f1bb
commit b596c6abe3
1 changed files with 328 additions and 312 deletions

View File

@ -5,25 +5,28 @@ Last-Modified: $Date$
Author: guido@python.org (Guido van Rossum) Author: guido@python.org (Guido van Rossum)
Status: Final Status: Final
Type: Standards Track Type: Standards Track
Content-Type: text/x-rst
Created: 8-Mar-2002 Created: 8-Mar-2002
Python-Version: 2.3 Python-Version: 2.3
Post-History: 8-Mar-2002, 30-Mar-2002, 3-Apr-2002 Post-History: 8-Mar-2002, 30-Mar-2002, 3-Apr-2002
Abstract Abstract
========
This PEP proposes the introduction of a new built-in type, bool, This PEP proposes the introduction of a new built-in type, bool,
with two constants, False and True. The bool type would be a with two constants, ``False`` and ``True``. The bool type would be a
straightforward subtype (in C) of the int type, and the values straightforward subtype (in C) of the int type, and the values
False and True would behave like 0 and 1 in most respects (for ``False`` and ``True`` would behave like 0 and 1 in most respects (for
example, False==0 and True==1 would be true) except repr() and example, ``False==0`` and ``True==1`` would be true) except ``repr()`` and
str(). All built-in operations that conceptually return a Boolean ``str()``. All built-in operations that conceptually return a Boolean
result will be changed to return False or True instead of 0 or 1; result will be changed to return ``False`` or ``True`` instead of 0 or 1;
for example, comparisons, the "not" operator, and predicates like for example, comparisons, the "not" operator, and predicates like
isinstance(). ``isinstance()``.
Review Review
======
I've collected enough feedback to last me a lifetime, so I declare I've collected enough feedback to last me a lifetime, so I declare
the review period officially OVER. I had Chinese food today; my the review period officially OVER. I had Chinese food today; my
@ -46,9 +49,9 @@ Review
More about that below too. I think this is not a sufficient More about that below too. I think this is not a sufficient
reason to reject the PEP. reason to reject the PEP.
2) Should str(True) return "True" or "1"? "1" might reduce 2) Should ``str(True)`` return "True" or "1"? "1" might reduce
backwards compatibility problems, but looks strange. backwards compatibility problems, but looks strange.
(repr(True) would always return "True".) (``repr(True)`` would always return "True".)
=> "True". => "True".
@ -73,17 +76,17 @@ Review
all, but most reviewers agree with me that bools should always all, but most reviewers agree with me that bools should always
allow arithmetic operations. allow arithmetic operations.
5) Should operator.truth(x) return an int or a bool? 5) Should ``operator.truth(x)`` return an int or a bool?
=> bool. => bool.
Tim Peters believes it should return an int, but almost all Tim Peters believes it should return an int, but almost all
other reviewers agree that it should return a bool. My other reviewers agree that it should return a bool. My
rationale: operator.truth() exists to force a Boolean context rationale: ``operator.truth()`` exists to force a Boolean context
on its argument (it calls the C API PyObject_IsTrue()). on its argument (it calls the C API ``PyObject_IsTrue())``.
Whether the outcome is reported as int or bool is secondary; if 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, bool exists there's no reason not to use it. (Under the PEP,
operator.truth() now becomes an alias for bool(); that's fine.) ``operator.truth()`` now becomes an alias for ``bool()``; that's fine.)
6) Should bool inherit from int? 6) Should bool inherit from int?
@ -93,7 +96,7 @@ Review
separate integer type that knows how to perform mixed-mode separate integer type that knows how to perform mixed-mode
arithmetic. However, inheriting bool from int eases the arithmetic. However, inheriting bool from int eases the
implementation enormously (in part since all C code that calls implementation enormously (in part since all C code that calls
PyInt_Check() will continue to work -- this returns true for ``PyInt_Check()`` will continue to work -- this returns true for
subclasses of int). Also, I believe this is right in terms of subclasses of int). Also, I believe this is right in terms of
substitutability: code that requires an int can be fed a bool 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 and it will behave the same as 0 or 1. Code that requires a
@ -137,6 +140,7 @@ Review
Rationale Rationale
=========
Most languages eventually grow a Boolean type; even C99 (the new Most languages eventually grow a Boolean type; even C99 (the new
and improved C standard, not yet widely adopted) has one. and improved C standard, not yet widely adopted) has one.
@ -164,9 +168,11 @@ Rationale
The standard bool type can also serve as a way to force a value to 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 be interpreted as a Boolean, which can be used to normalize
Boolean values. When a Boolean value needs to be normalized to Boolean values. When a Boolean value needs to be normalized to
one of two values, bool(x) is much clearer than "not not x" and one of two values, ``bool(x)`` is much clearer than "not not x" and
much more concise than much more concise than
::
if x: if x:
return 1 return 1
else: else:
@ -174,7 +180,7 @@ Rationale
Here are some arguments derived from teaching Python. When Here are some arguments derived from teaching Python. When
showing people comparison operators etc. in the interactive shell, showing people comparison operators etc. in the interactive shell,
I think this is a bit ugly: I think this is a bit ugly::
>>> a = 13 >>> a = 13
>>> b = 12 >>> b = 12
@ -182,7 +188,7 @@ Rationale
1 1
>>> >>>
If this was: If this was::
>>> a > b >>> a > b
True True
@ -193,7 +199,7 @@ Rationale
There's also the issue (which I've seen baffling even experienced There's also the issue (which I've seen baffling even experienced
Pythonistas who had been away from the language for a while) that Pythonistas who had been away from the language for a while) that
if you see: if you see::
>>> cmp(a, b) >>> cmp(a, b)
1 1
@ -201,17 +207,18 @@ Rationale
0 0
>>> >>>
you might be tempted to believe that cmp() also returned a truth you might be tempted to believe that ``cmp()`` also returned a truth
value, whereas in reality it can return three different values value, whereas in reality it can return three different values
(-1, 0, 1). If ints were not (normally) used to represent ``(-1, 0, 1)``. If ints were not (normally) used to represent
Booleans results, this would stand out much more clearly as Booleans results, this would stand out much more clearly as
something completely different. something completely different.
Specification Specification
=============
The following Python code specifies most of the properties of the The following Python code specifies most of the properties of the
new type: new type::
class bool(int): class bool(int):
@ -258,26 +265,26 @@ Specification
False = int.__new__(bool, 0) False = int.__new__(bool, 0)
True = int.__new__(bool, 1) True = int.__new__(bool, 1)
The values False and True will be singletons, like None. Because The values ``False`` and ``True`` will be singletons, like None. Because
the type has two values, perhaps these should be called the type has two values, perhaps these should be called
"doubletons"? The real implementation will not allow other "doubletons"? The real implementation will not allow other
instances of bool to be created. instances of bool to be created.
True and False will properly round-trip through pickling and ``True`` and ``False`` will properly round-trip through pickling and
marshalling; for example pickle.loads(pickle.dumps(True)) will marshalling; for example ``pickle.loads(pickle.dumps(True))`` will
return True, and so will marshal.loads(marshal.dumps(True)). return ``True``, and so will ``marshal.loads(marshal.dumps(True))``.
All built-in operations that are defined to return a Boolean All built-in operations that are defined to return a Boolean
result will be changed to return False or True instead of 0 or 1. result will be changed to return ``False`` or ``True`` instead of 0 or 1.
In particular, this affects comparisons (<, <=, ==, !=, >, >=, is, In particular, this affects comparisons (``<``, ``<=``, ``==``, ``!=``,
is not, in, not in), the unary operator 'not', the built-in ``>``, ``>=``, is, is not, in, not in), the unary operator 'not', the built-in
functions callable(), hasattr(), isinstance() and issubclass(), functions ``callable()``, ``hasattr()``, ``isinstance()`` and ``issubclass()``,
the dict method has_key(), the string and unicode methods the dict method ``has_key()``, the string and unicode methods
endswith(), isalnum(), isalpha(), isdigit(), islower(), isspace(), ``endswith()``, ``isalnum()``, ``isalpha()``, ``isdigit()``, ``islower()``, ``isspace()``,
istitle(), isupper(), and startswith(), the unicode methods ``istitle()``, ``isupper()``, and ``startswith()``, the unicode methods
isdecimal() and isnumeric(), and the 'closed' attribute of file ``isdecimal()`` and ``isnumeric()``, and the 'closed' attribute of file
objects. The predicates in the operator module are also changed objects. The predicates in the operator module are also changed
to return a bool, including operator.truth(). to return a bool, including ``operator.truth()``.
Because bool inherits from int, True+1 is valid and equals 2, and Because bool inherits from int, True+1 is valid and equals 2, and
so on. This is important for backwards compatibility: because so on. This is important for backwards compatibility: because
@ -286,38 +293,40 @@ Specification
values. values.
It is expected that over time, the standard library will be It is expected that over time, the standard library will be
updated to use False and True when appropriate (but not to require updated to use ``False`` and ``True`` when appropriate (but not to require
a bool argument type where previous an int was allowed). This a bool argument type where previous an int was allowed). This
change should not pose additional problems and is not specified in change should not pose additional problems and is not specified in
detail by this PEP. detail by this PEP.
C API C API
=====
The header file "boolobject.h" defines the C API for the bool 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 type. It is included by "Python.h" so there is no need to include
it directly. it directly.
The existing names Py_False and Py_True reference the unique bool The existing names ``Py_False`` and ``Py_True`` reference the unique bool
objects False and True (previously these referenced static int objects ``False`` and ``True`` (previously these referenced static int
objects with values 0 and 1, which were not unique amongst int objects with values 0 and 1, which were not unique amongst int
values). values).
A new API, PyObject *PyBool_FromLong(long), takes a C long int A new API, ``PyObject *PyBool_FromLong(long)``, takes a C long int
argument and returns a new reference to either Py_False (when the argument and returns a new reference to either ``Py_False`` (when the
argument is zero) or Py_True (when it is nonzero). argument is zero) or ``Py_True`` (when it is nonzero).
To check whether an object is a bool, the macro PyBool_Check() can To check whether an object is a bool, the macro ``PyBool_Check()`` can
be used. be used.
The type of bool instances is PyBoolObject *. The type of bool instances is ``PyBoolObject *``.
The bool type object is available as PyBool_Type. The bool type object is available as PyBool_Type.
Clarification Clarification
=============
This PEP does *not* change the fact that almost all object types This PEP does **not** change the fact that almost all object types
can be used as truth values. For example, when used in an if 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; 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. this does not change and there is no plan to ever change this.
@ -325,16 +334,17 @@ Clarification
The only thing that changes is the preferred values to represent The only thing that changes is the preferred values to represent
truth values when returned or assigned explicitly. Previously, truth values when returned or assigned explicitly. Previously,
these preferred truth values were 0 and 1; the PEP changes the these preferred truth values were 0 and 1; the PEP changes the
preferred values to False and True, and changes built-in preferred values to ``False`` and ``True``, and changes built-in
operations to return these preferred values. operations to return these preferred values.
Compatibility Compatibility
=============
Because of backwards compatibility, the bool type lacks many Because of backwards compatibility, the bool type lacks many
properties that some would like to see. For example, arithmetic properties that some would like to see. For example, arithmetic
operations with one or two bool arguments is allowed, treating operations with one or two bool arguments is allowed, treating
False as 0 and True as 1. Also, a bool may be used as a sequence ``False`` as 0 and ``True`` as 1. Also, a bool may be used as a sequence
index. index.
I don't see this as a problem, and I don't want evolve the I don't see this as a problem, and I don't want evolve the
@ -354,10 +364,11 @@ Compatibility
Resolved Issues Resolved Issues
===============
(See also the Review section above.) (See also the Review section above.)
- Because the repr() or str() of a bool value is different from an - Because the ``repr()`` or ``str()`` of a bool value is different from an
int value, some code (for example doctest-based unit tests, and int value, some code (for example doctest-based unit tests, and
possibly database code that relies on things like "%s" % truth) possibly database code that relies on things like "%s" % truth)
may fail. It is easy to work around this (without explicitly may fail. It is easy to work around this (without explicitly
@ -367,20 +378,22 @@ Resolved Issues
- Other languages (C99, C++, Java) name the constants "false" and - Other languages (C99, C++, Java) name the constants "false" and
"true", in all lowercase. For Python, I prefer to stick with "true", in all lowercase. For Python, I prefer to stick with
the example set by the existing built-in constants, which all the example set by the existing built-in constants, which all
use CapitalizedWords: None, Ellipsis, NotImplemented (as well as use CapitalizedWords: ``None``, ``Ellipsis``, ``NotImplemented`` (as well as
all built-in exceptions). Python's built-in namespace uses all all built-in exceptions). Python's built-in namespace uses all
lowercase for functions and types only. lowercase for functions and types only.
- It has been suggested that, in order to satisfy user - It has been suggested that, in order to satisfy user
expectations, for every x that is considered true in a Boolean expectations, for every x that is considered true in a Boolean
context, the expression x == True should be true, and likewise context, the expression ``x == True`` should be true, and likewise
if x is considered false, x == False should be true. In if x is considered false, ``x == False`` should be true. In
particular newbies who have only just learned about Boolean particular newbies who have only just learned about Boolean
variables are likely to write variables are likely to write
::
if x == True: ... if x == True: ...
instead of the correct form, instead of the correct form,
::
if x: ... if x: ...
@ -388,29 +401,32 @@ Resolved Issues
many people are at first uncomfortable with the latter form, but many people are at first uncomfortable with the latter form, but
I believe that the solution should be in education rather than I believe that the solution should be in education rather than
in crippling the language. After all, == is general seen as a in crippling the language. After all, == is general seen as a
transitive operator, meaning that from a==b and b==c we can transitive operator, meaning that from ``a==b`` and ``b==c`` we can
deduce a==c. But if any comparison to True were to report deduce ``a==c``. But if any comparison to ``True`` were to report
equality when the other operand was a true value of any type, equality when the other operand was a true value of any type,
atrocities like 6==True==7 would hold true, from which one could atrocities like ``6==True==7`` would hold true, from which one could
infer the falsehood 6==7. That's unacceptable. (In addition, infer the falsehood ``6==7``. That's unacceptable. (In addition,
it would break backwards compatibility. But even if it didn't, it would break backwards compatibility. But even if it didn't,
I'd still be against this, for the stated reasons.) I'd still be against this, for the stated reasons.)
Newbies should also be reminded that there's never a reason to Newbies should also be reminded that there's never a reason to
write write
::
if bool(x): ... if bool(x): ...
since the bool is implicit in the "if". Explicit is *not* since the bool is implicit in the "if". Explicit is **not**
better than implicit here, since the added verbiage impairs better than implicit here, since the added verbiage impairs
redability and there's no other interpretation possible. There redability and there's no other interpretation possible. There
is, however, sometimes a reason to write is, however, sometimes a reason to write
::
b = bool(x) b = bool(x)
This is useful when it is unattractive to keep a reference to an This is useful when it is unattractive to keep a reference to an
arbitrary object x, or when normalization is required for some arbitrary object x, or when normalization is required for some
other reason. It is also sometimes appropriate to write other reason. It is also sometimes appropriate to write
::
i = int(bool(x)) i = int(bool(x))
@ -419,21 +435,21 @@ Resolved Issues
Implementation Implementation
==============
A complete implementation in C has been uploaded to the A complete implementation in C has been uploaded to the
SourceForge patch manager: SourceForge patch manager: http://python.org/sf/528022
http://python.org/sf/528022
This will soon be checked into CVS for python 2.3a0. This will soon be checked into CVS for python 2.3a0.
Copyright Copyright
=========
This document has been placed in the public domain. This document has been placed in the public domain.
..
Local Variables: Local Variables:
mode: indented-text mode: indented-text
indent-tabs-mode: nil indent-tabs-mode: nil