Why did Python introduce Boolean types 18 years ago? And different from C, C + + and Java?

Time:2020-10-26

Why can Python support arbitrary truth value judgment? 》In this paper, we analyze the underlying implementation of Python in truth value judgment, and we can see that Python adopts a relatively broad attitude towards Boolean value. What is the official thinking about this?

The following article is pep-285, written by Guido van Rossum, the father of Python. This PEP is of great significance. The bool type of Python was introduced from it. Many problems I analyzed in the last article can be explained in this document more than ten years ago! In addition, it also responds to some typical controversies, which is worth understanding.

PEP original text: https://www.python.org/dev/peps/pep-0285/

PEP Title: PEP 285 — Adding a bool type

PEP Author: Guido van Rossum

Creation date: 2002-03-08

Combined version: 2.3

translatorTofu pudding cat @Python public official account

PEP translation plan :https://github.com/chinesehua…

outline

This PEP proposes to introduce a new built-in typebool, which will contain two constantsFalseandTrue。 This bool type is a direct subtype of type int (in C), and in most aspects except repr() and str(), its value isFalseandTrueWill behave like 0 and 1 (for example, false = = 0 and true = = 1 are both true).

All built-in operations that conceptually need to return Boolean results will be changed to return false or true instead of 0 or 1, such as comparison operation, not operation and assertion methods such as isinstance().

review

I’ve collected too much feedback, so I announce that the review period is formalend.I have Chinese food today. My signature cake says “strong and bitter words indicate a weak cause.” it reminds me of some posts against this PEP…: -)

(Note: 1. Fortune cookies, a feature of American culture. Chinese restaurants in the United States at the time of check-out popular to the guests some signed biscuits, generally is a blessing. 2. That sign comes from Victor Hugo, which means: the wrongdoer speaks fiercely)

Anyway, these are my bdfl statements. Executive Summary: I will not change anything; all other proposals will be rejected.)

1. Should this PEP be accepted?

=>Yes.

There are many arguments against this pep. Most of them are out of misunderstanding. I have tried to clarify some of the most common misunderstandings in the PEP text below. For me, the only thing worth considering is that novices tend to write “if x = = true,” but “if x” is enough. There is more information about it below. I don’t think it’s enough to reject this pep.

2、str(True)Should I return “true” or “1”? “1” may reduce backward compatibility issues, but it seems strange. (repr(True)Will always return true.)

=>“True”。

Almost all reviewers agree.

3. Should constants be named “true” and “false” (similar to none) or “true” and “false” (like C + +, Java, and C99)?

=>True and false.

Most reviewers agree that consistency within Python is more important than consistency with other languages.

4. Should non Boolean operations on Boolean values be eliminated by appropriate alarms so that true + 1, for example, becomes illegal (in Python 3000)?

=>Should not

A small number of people with strong views would like to see the “textbook type” boolean type, that is, it does not support arithmetic operations at all, but most reviewers agree with me that Boolean types should support arithmetic operations.

5、operator.truth(x)Should I return int or bool?

=>bool。

Tim Peters believes that an integer should be returned, but almost all other reviewers believe that a Boolean value should be returned. My reason: operator.truth () means to force its parameters to use a boolean type context (which calls the C APIPyObject_IsTrue())。 Whether the result is int or bool, it is secondary; if there is a bool, there is no reason not to use it. (under this PEP, operator.truth () has become an alias for bool (); that’s OK.)

6. Should bool inherit from int?

=>Yes.

Ideally, bool is best implemented as a separate integer type and supports mixed arithmetic operations. However, inheriting bool from int will greatly simplify the implementation (in part because all callsPyInt_Check()C code is compatible — it returns true for subclasses of int).

In addition, I think this fits into the concept of substitutability: when an int is needed in your code, you can feed bool, which is equal to 0 or 1. When bool is required in the code, if int is given, it may not be as expected; for example, 3 & 4 evaluates to 0, but when 3 and 4 are considered true, they are both true.

7. Should we change the name of bool?

=>No.

Some reviewers advocate using Boolean instead of bool because it’s easier to understand (novices may have heard of Boolean algebra, but may not be interested in bool), or because they hate abbreviations.

My point: Python uses abbreviations wisely (e.g. ‘def’,’int ‘,’dict’), and I don’t think it’s a burden to understand. For beginners, it doesn’t matter whether it’s called waffle or bool; it’s just a new word, and they’ll soon be able to grasp its meaning.

Waffle, as we all know, means “waffle”, but it also means “meaningless, unimportant, nonsense”

One reviewer thought it could be called “truth.”. I don’t find this term attractive, but I prefer to keep the term (in the documentation) to refer to specific truth concepts that already exist in Python. For example, “when a container is interpreted as a truth value, empty containers are treated as false, and non empty containers are treated as true.”.

8. Should Boolean operators (such as “if”, “and” and “not”) be required to use a Boolean value as a parameter in the future. For example, if []] is illegal, it must be written as “if bool (()):???

=>No!!!

Some people think this is what a textbook Boolean language should do. Because it was mentioned, others were worried that I might agree with it.

Let me clarify my position on this: This is not the motivation of this PEP and I have no intention of changing it. (see also the clarification section below.)

Basic principles

Most languages will eventually develop a boolean type, and even C99 (the new improved C standard, not widely adopted) has one.(Note: the C99 standard was born in 1999, and this PEP was written in 2002. The situation has changed, and now the C99 standard is basically outdated.)

Many programmers feel the need for a boolean type, and most Python documents are apologetic for the lack of Boolean types. I’ve seen many modules that define the constants “false = 0” and “true = 1” (or similar) at the top and use them.

The problem is that everyone does it differently. For example, should you use “false”, “false”, “false”, “F” or “F”? In addition, should the false value be 0 or none, or is it a boolean type that prints “true” or “false”? Adding a standard Boolean type to the language can solve these problems.

Some external libraries (such as database and RPC related packages) need to be able to distinguish between Boolean and integer values, and while solutions can usually be developed, it is easier if the language itself provides standard Boolean types. This also applies to Jython: some Java classes have overloaded methods or constructors for int and Boolean arguments, respectively. Boolean types can be used to select Boolean variables. (this is obviously true for some COM interfaces.)

The standard Boolean type can also be used as a way to force values to be interpreted as Boolean values, which can be used to standardize Boolean values. When a Boolean value needs to be normalized to one of two values, bool (x) is clearer than “not not X”, and is more concise than this method

if x:
    return 1
else:
    return 0

Here are some lessons from teaching python. When showing people comparison operators in interactive terminals, I think it’s a bit ugly:

>>> a = 13
>>> b = 12
>>> a > b
1
>>>

If so:

>>> a > b
True
>>>

It takes a millisecond less to think about the printed 0 or 1 at a time.

There is also a problem (it even bothers people who have been experienced but have been away from Python for some time): the

>>> cmp(a, b)
1
>>> cmp(a, a)
0
>>>

You might be inclined to think that CMP () also returns a Boolean value, but in fact it can return three different values (- 1, 0, 1). If integers are not (usually) used to represent Boolean results, this can be more obvious in other meanings.If only true / false is used to express Boolean value, then there will be no ambiguity when integers express other meanings

standard

The following Python code details most of the properties of the new type:

class bool(int):

    def __new__(cls, val=0):
        # This constructor always returns an existing instance
        if val:
            return True
        else:
            return False

    def __repr__(self):
        if self:
            return "True"
        else:
            return "False"

    __str__ = __repr__

    def __and__(self, other):
        if isinstance(other, bool):
            return bool(int(self) & int(other))
        else:
            return int.__and__(self, other)

    __rand__ = __and__

    def __or__(self, other):
        if isinstance(other, bool):
            return bool(int(self) | int(other))
        else:
            return int.__or__(self, other)

    __ror__ = __or__

    def __xor__(self, other):
        if isinstance(other, bool):
            return bool(int(self) ^ int(other))
        else:
            return int.__xor__(self, other)

    __rxor__ = __xor__

# Bootstrap truth values through sheer willpower
False = int.__new__(bool, 0)
True = int.__new__(bool, 1)

False and true will be singletons, like none. Because this type has two values, maybe they should be called “doubles”? The actual implementation will not allow other instances of bool to be created.

True and false are properly serialized and packaged, such as pickle.loads ( pickle.dumps (true)) will return true, and marshal.loads ( marshal.dumps (true)).

All built-in operations that are defined to return Boolean results are changed to return false or true instead of 0 or 1.

Specifically, this will affect the comparison operation (<, < =, = =,! =, >, > =, is, is not, in, not in), unary operator ‘not’, built-in functions callable(), hasattr(), isinstance() and issubclass(), dictionary method has_ Key(), string and Unicode methods endswitch(), isalnum(), isalpha(), isdigit(), islower(), isspace(), istile(), isupper() and startswitch(), Unicode methods isdecimal() and isnumeric(), and the “closed” attribute of the file object. The assertion method in the operator module has also been changed to return Boolean values, including operator.truth ()。

Because bool inherits from int, true + 1 is valid and equal to 2, and so on. This is important for backward compatibility: because operations such as comparisons currently return integer values, it is not possible to determine how these values are used by existing applications.

It is expected that over time, the standard library will be updated to use false and true when appropriate (but bool parameter types are not required where int was previously allowed). This change should not cause other problems not detailed in this pep.

C API

The “boolobject. H” header file defines the C API for Boolean types. It’s included in “python. H,” so you don’t need to include it any more.

Existing name PY_ False and PY_ True refers to the unique Boolean objects false and true (previously, they referred to static integer objects with values of 0 and 1, respectively, being one of many integers).

A new API, namelyPyObject *PyBool_FromLong(long), will receive a C long integer parameter and return a pair of_ False (when the parameter is zero) or py_ True (when nonzero).

To check whether an object is a Boolean object, you can use the macro pybool_ Check()。

The type of Boolean instance is pyboolobject *.

Boolean type objects can be used as pybool_ Type.

clarify

This PEP does not change the fact that almost all types of objects can be used as true and false values. For example, when used in an IF statement, an empty list is false and a non empty list is true; this does not change and is not intended to change.

The only change is the preferred value used to represent true and false values when returning or assigning values. Previously, these preferred true and false values were 1 and 0; this PEP changes the preferred values to true and false and modifies the built-in operation to return them.

compatibility

Boolean types have some lax properties because they are backward compatible. For example, Boolean parameters are allowed for arithmetic operations, where false is treated as 0 and true as 1. Moreover, bool can be used as an index for sequence objects.

I don’t think it’s a problem, and I don’t want to develop language in this direction. I don’t think a stricter interpretation of “Boolean” will make the language clearer.

Another result of compatibility requirements is that the expression “true and 6” has a value of 6, and similarly the expression “false or none” has a value of none.

The “and” and “or” operators are designed to return the first parameter that determines the result; in particular, they do not force the result to be Boolean. Of course, if both parameters are Boolean, the result must be a Boolean. By writing “bool (x and y)”, it is also easy to force it to a boolean type.

Problems solved

(see also the review section above.)

  • Some code (for example, doctest based unit tests, and database code that may depend on the% s% truth) may be wrong because the repr() or str() of the bool value is different from the int value. It’s easy to solve this problem (without explicitly referring to bool types), and it’s expected to affect only a very small amount of code that can be easily fixed.
  • Other languages (C99, C + +, Java) name constants “false” and “true” in lowercase. For Python, I prefer to follow the conventions of existing built-in constants, all of which are named hump: none, ellipsis, not implemented (and all built-in exceptions). Python’s built-in namespace all uses lowercase letters to represent functions and types.
  • As mentioned earlier, in order to satisfy the user’s expectations, for every X that is considered true in a Boolean context,x == TrueExpressions should be true, again, if x is considered false, thenx == FalseIt should also be true. Those who are new to Boolean variables may write:

    if x == True: ...

    Not in the right form:

    if x: ...

    There seems to be strong psychological and linguistic reasons for many people to feel uncomfortable with the latter form at first sight, but I think the solution should be to educate rather than weaken the language.

    After all, = = is usually considered a transitive symbol, which means that a = = C can be inferred from a = = B and B = = C. However, if a number is true and the result of comparison with true is equal, then brutality like 6 = = true = = 7 will hold, thus inferring the wrong 6 = = 7. That is not acceptable. (in addition, it destroys backward compatibility. But even if it doesn’t break, I’m still against it for the reasons above.)

    The novice should also be reminded that there is no reason to write:

    if bool(x): ...

    Because Boolean values are implicit in “if.”. Here, explicit andNoIt’s better than implicit, because the added lexical damages reusability and limits the interpreter’s interpretation behavior.(Note: “the Zen of Python thinks” explicit “is better than implicit,” but here Guido thinks implicit is better, so he roughens “not” in the original document.)

    However, sometimes there is a reason to write:

    b = bool(x)

    This is useful when you don’t need to keep a reference to any x object, or when normalization is needed for some other reason. Sometimes it’s appropriate to write like this:

    i = int(bool(x))

    It converts a Boolean value to 0 or 1 of an integer. Conveys the intention to use the value as an int.

realization

The complete C implementation code has been uploaded to the SourceForge patch Manager: https://bugs.python.org/issue…

It will soon be incorporated into the CVs of Python 2.3a0.

copyright

This document has entered the public domain.

Source document: https://github.com/python/pep…

More Chinese translations of PEP can be found at GitHub: https://github.com/chinesehua…