Why can Python support arbitrary truth judgment?

Time:2020-11-2

This article is from the “why Python” series, please check out the full article

Python is involved inTruth value judgment(truth value testing).

For example, when judging whether an object is not none or whether the container object is not empty, it is not necessary to write out the judgment condition explicitly, but to write the object directly after the if or while keywords.

The following figure takes a list as an example,if my_listThis short way of writing can express two meanings

Why can Python support arbitrary truth judgment?

If you need to make the opposite judgment, that is, “if none or empty”, you just need to writeif not my_listThat’s fine.

Different way to judge truth value

Generally speaking, when a value itself is a boolean type, it is semantically easy to understand if XXX (if true). If XXX itself is not a boolean type, it is not semantically easy to understand if XXX is written as “if XXX” (if something).

In C / C + + / Java and so onStatic languageIn order to get the result of a Boolean value, it is usually necessary to make a comparison operation based on XXX, such as “if (XXX = = null)”, and then determine the true value. Otherwise, if there is a non Boolean value in “if XXX”, a type error will be reported.

PythonDynamic languageIn this scenario, there is a kind of flexibility. Then, we have a problem:Why does Python not need to do a comparison operation first, so it can judge the truth value of any object directly?

Let’s take a look at the description of truth value judgment in the document

Why can Python support arbitrary truth judgment?

In short, any Python object can be used in if or while or Boolean operations (and, or, not), and is considered true by default, unless it has one__ bool__ () method returnFalseOr there are__ len__ () method return0

For the previous example, my_ List no__ bool__ () method, but it has__ len__ () method, so whether it is true depends on the return value of this method.

Bytecode of truth judgment

Then we went on to get to the bottom of the matter:Why can Python support such a wide range of truth judgments? In executionif xxxWhat is it doing with such a statement?

For the first problem, python has a built-in bool () type that converts any object to a Boolean value. So, does this mean that Python willImplicitlyWhat about calling bool() (that is, converting toif bool(xxx))? (the answer is no, which is analyzed below)

For the second question, you can use thedisModule to view the following:

Why can Python support arbitrary truth judgment?

POP_JUMP_IF_FALSEThe instruction corresponds to the line of if statement

If TOS is false, sets the bytecode counter to _target_. TOS is popped.

If the top element of the stack is false, it jumps to the target location.

There is only a description of the jump action, and there is still no way to see how a normal object becomes a Boolean object.

How does Python implement truth judgment in the interpreter?

Source code implementation of truth judgment

With the help of Jo, a wechat group friend, I found the source code of Cpython (files: ceval. C, object. C)

Why can Python support arbitrary truth judgment?

Why can Python support arbitrary truth judgment?

As you can see, for objects of boolean type (py_ True and PY_ False), the code will enter the branch of fast processing; for other objects, pyobject will be used_ Istrue() calculates a value of type int.

PyObject_ The istrue() function gets Nb in turn during the calculation_ bool、mp_ Length and sq_ The value of length should be__ bool__ () and__ len__ () the return value of these two magic methods.

This process is the description of the official documents quoted in the previous article, which is exactly the answer we want to find!

In addition, for the built-in bool (), its core implementation logic is the pyobject above_ Istrue() function. The source code is as follows (boolobject. C)

Why can Python support arbitrary truth judgment?

Therefore, python does not call bool () implicitly when it judges the truth value of ordinary objects. On the contrary, it calls an independent function (pyobject)_ Istrue ()), which is used by bool().

in other words,In fact, bool () and if / while statements are basically the same processing logic for common objects.You’ll understand the principleif bool(xxx)This kind of writing is superfluous (I have seen it before).

So far, we have answered the questions raised above.

The process of verifying truth value judgment

Next, there are three test examples for further verification

Why can Python support arbitrary truth judgment?

You can pause and think:bool(Test1)Andbool(Test1())What are the results? Then judge the remaining two classes in turn. What will the result be?

Answer:

bool(Test1)   # True
bool(Test2)   # True
bool(Test3)   # True

bool(Test1()) # True
bool(Test2()) # False
bool(Test3()) # True

The reasons are as follows:

  • When the class object is not instantiated, bool () will not call it__ bool__ () or__ len__ () these two magic methods
  • After class objects are instantiated, if they exist at the same time__ bool__ () or__ len__ () magic method, bool() will call__ bool__ () method (PS: this method requires that the return value must be of bool type, so as long as it is available, it must not be used again__ len__ () to judge whether it is true or not)

How to judge the truth value of digital type?

In addition to these three examples, there is another situation worthy of verification, that isHow do they make truth judgments for numeric types?

We can verify whether the number type has those two magic methods:

hasattr(2020, “__bool__”)
hasattr(2020, “__len__”)

It’s not hard to verify that what numbers have is__ bool__ () magic method, No__ len__ () magic method, and all types of numbers are actually divided into two categories:

  • __bool__()Returns false: all numbers representing 0, such as0, 0.0, 0j, Decimal(0), Fraction(0, 1)
  • __bool__()Returns true: all other non-zero numbers

prose summary

In Pythonif xxxAlthough it is a normal truth value judgment grammar, it does not conform to the conventional semantics. In languages such as C / C + + / Java, XXX itself is a Boolean value or an operation that can return Boolean type value. However, in Python, the “XXX” can also be a Boolean valueAny Python object!

By analyzing the source code of document, bytecode and Cpython interpreter step by step, we find that the process of judging Python truth value is not simple, and we can extract the following points:

  • If / while is an implicit Boolean operator:They not only have the function of “judging” true or false, but also have the function of implicitly calculating the Boolean results of ordinary objects. The actual operation of the interpreter is based on “pop”_ JUMP_ IF_ The core logic and the built-in bool() share the same underlying method
  • The truth judgment process depends on two magic methodsUnless the subject is judged to have__ bool__ () method returnFalseOr there are__ len__ () method return0Otherwise, the result of the Boolean operation is true. Two magic methods always calculate first__ bool__ ()
  • The number type can also be used to judge the truth valueThe numbers are__ bool__ () magic method, but no__ len__ () magic method, except that the number indicating 0 is false, all other numbers are true

If you think the analysis of this article is good, you should like these articles:

1. Why does Python use indentation to divide code blocks?

2. Is Python’s indentation an anti human design?

3. Why don’t Python use semicolons as statement terminators?

4. Why does Python have no main function? Why don’t I recommend writing the main function?

5. Why Python recommends snake nomenclature?

6. Why does Python not support I + + auto increment syntax and provide + + operators?

7. Why can Python exchange two variables directly with one statement “a, B = B, a”?

8. Why does Python use the symbol?

9. Why does Python have a pass statement?

10. Why does Python have a strange “…” object?

This article belongs to the “why Python” series (produced by Python cat). This series focuses on the syntax, design and development of python, and tries to show the charm of Python by taking “why” questions as the starting point. All articles will be filed on GitHub, project address: https://github.com/chinesehuazhou/python-whydo