Movatterモバイル変換


[0]ホーム

URL:


— FREE Email Series —

🐍 Python Tricks 💌

Python Tricks Dictionary Merge

🔒 No spam. Unsubscribe any time.

Browse TopicsGuided Learning Paths
Basics Intermediate Advanced
apibest-practicescareercommunitydatabasesdata-sciencedata-structuresdata-vizdevopsdjangodockereditorsflaskfront-endgamedevguimachine-learningnumpyprojectspythontestingtoolsweb-devweb-scraping

Table of Contents

Recommended Video Course
Python Booleans: Leveraging the Values of Truth

Python Booleans: Optimize Your Code With Truth Values

Python Booleans: Use Truth Values in Your Code

byMoshe Zadkaintermediatepython

Table of Contents

Remove ads

Watch Now This tutorial has a related video course created by the Real Python team. Watch it together with the written tutorial to deepen your understanding:Python Booleans: Leveraging the Values of Truth

ThePython Boolean type is one of Python’sbuilt-in data types. It’s used to represent the truth value of an expression. For example, the expression1 <= 2 isTrue, while the expression0 == 1 isFalse. Understanding how Python Boolean values behave is important to programming well in Python.

In this tutorial, you’ll learn how to:

  • Manipulate Boolean values withBoolean operators
  • Convert Booleans toother types
  • Convert other types toPython Booleans
  • Use Python Booleans to writeefficient and readable Python code

Free Bonus:5 Thoughts On Python Mastery, a free course for Python developers that shows you the roadmap and the mindset you’ll need to take your Python skills to the next level.

The Python Boolean Type

The Python Boolean type has only two possible values:

  1. True
  2. False

No other value will havebool as its type. You can check the type ofTrue andFalse with the built-intype():

Python
>>>type(False)<class 'bool'>>>>type(True)<class 'bool'>

Thetype() of bothFalse andTrue isbool.

The typebool isbuilt in, meaning it’s always available in Python and doesn’t need to be imported. However, the name itself isn’t a keyword in the language. While the following is considered bad style, it’s possible to assign to the namebool:

Python
>>>bool<class 'bool'>>>>bool="this is not a type">>>bool'this is not a type'

Although technically possible, to avoid confusion it’s highly recommended that you don’t assign a different value tobool.

Python Booleans as Keywords

Built-in names aren’t keywords. As far as the Python language is concerned, they’re regularvariables. If you assign to them, then you’ll override the built-in value.

In contrast, the namesTrue andFalse arenot built-ins. They’rekeywords. Unlike many otherPython keywords,True andFalse are Pythonexpressions. Since they’re expressions, they can be used wherever other expressions, like1 + 1, can be used.

It’s possible to assign a Boolean value to variables, but it’s not possible to assign a value toTrue:

Python
>>>a_true_alias=True>>>a_true_aliasTrue>>>True=5  File"<stdin>", line1SyntaxError:cannot assign to True

BecauseTrue is a keyword, you can’t assign a value to it. The same rule applies toFalse:

Python
>>>False=5  File"<stdin>", line1SyntaxError:cannot assign to False

You can’t assign toFalse because it’s a keyword in Python. In this way,True andFalse behave like other numeric constants. For example, you can pass1.5 to functions or assign it to variables. However, it’s impossible to assign a value to1.5. The statement1.5 = 5 is not valid Python. Both1.5 = 5 andFalse = 5 are invalid Python code and will raise aSyntaxError when parsed.

Python Booleans as Numbers

Booleans are considered anumeric type in Python. This means they’renumbers for all intents and purposes. In other words, you can apply arithmetic operations to Booleans, and you can also compare them to numbers:

Python
>>>True==1True>>>False==0True>>>True+(False/True)1.0

There aren’t many uses for the numerical nature of Boolean values, but there’s one technique you may find helpful. BecauseTrue is equal to1 andFalse is equal to0, adding Booleans together is a quick way to count the number ofTrue values. This can come in handy when you need to count the number of items that satisfy a condition.

For example, if you want to analyze a verse in aclassic children’s poem to see what fraction of lines contain the word"the", then the fact thatTrue is equal to1 andFalse is equal to0 can come in quite handy:

Python
>>>lines="""\...He took his vorpal sword in hand;...      Long time the manxome foe he sought—...So rested he by the Tumtum tree...      And stood awhile in thought....""".splitlines()>>>sum("the"inline.lower()forlineinlines)/len(lines)0.5

Summing all values in agenerator expression like this lets you know how many timesTrue appears in the generator. The number of timesTrue is in the generator is equal to the number of lines that contain the word"the", in a case-insensitive way. Dividing this number by the total number of lines gives you the ratio of matching lines to total lines.

To see why this works, you can break the above code into smaller parts:

Python
>>>lines="""\...He took his vorpal sword in hand;...      Long time the manxome foe he sought—...So rested he by the Tumtum tree...      And stood awhile in thought....""">>>line_list=lines.splitlines()>>>"the"inline_list[0]False>>>"the"inline_list[1]True>>>0+False+True# Equivalent to 0 + 0 + 11>>>["the"inlineforlineinline_list][False, True, True, False]>>>False+True+True+False2>>>len(line_list)4>>>2/40.5

Theline_list variable holds a list of lines. The first line doesn’t have the word"the" in it, so"the" in line_list[0] isFalse. In the second line,"the" does appear, so"the" in line_list[1] isTrue. Since Booleans are numbers, you can add them to numbers, and0 + False + True gives1.

Since["the" in line for line in line_list] is a list of four Booleans, you can add them together. When you addFalse + True + True + False, you get2. Now, if you divide that result by4, the length of the list, you get0.5. The word"the" appears in half the lines in the selection. This is a useful way to take advantage of the fact that Booleans are numbers.

Boolean Operators

Boolean operators are those that takeBoolean inputs and returnBoolean results.

Note: Later, you’ll see that these operators can be given other inputs and don’t always return Boolean results. For now, all examples will use Boolean inputs and results. You’ll see how this generalizes to other values in the section ontruthiness.

Since Python Boolean values have only two possible options,True orFalse, it’s possible to specify the operators completely in terms of the results they assign to every possible input combination. These specifications are calledtruth tables since they’re displayed in a table.

As you’ll see later, in some situations, knowing one input to an operator is enough to determine its value. In those cases, the other input isnot evaluated. This is calledshort-circuit evaluation.

The importance of short-circuit evaluation depends on the specific case. In some cases, it might have little effect on your program. In other cases, such as when it would be computationally intensive to evaluate expressions that don’t affect the result, it provides a significant performance benefit. In the most extreme cases, the correctness of your code can hinge on the short-circuit evaluation.

Operators With No Inputs

You can think ofTrue andFalse as Boolean operators that take no inputs. One of these operators always returnsTrue, and the other always returnsFalse.

Thinking of the Python Boolean values as operators is sometimes useful. For example, this approach helps to remind you that they’re not variables. For the same reason you can’t assign to+, it’s impossible to assign toTrue orFalse.

Only two Python Boolean values exist. A Boolean operator with no inputs always returns the same value. Because of this,True andFalse are the only two Boolean operators that don’t take inputs.

Thenot Boolean Operator

The only Boolean operator with one argument isnot. It takes one argument and returns the opposite result:False forTrue andTrue forFalse. Here it is in a truth table:

Anot A
TrueFalse
FalseTrue

This table illustrates thatnot returns the opposite truth value of the argument. Sincenot takes only one argument, it doesn’t short-circuit. It evaluates its argument before returning its result:

Python
>>>notTrueFalse>>>notFalseTrue>>>defprint_and_true():...print("I got called")...returnTrue...>>>notprint_and_true()I got calledFalse

The last line shows thatnot evaluates its input before returningFalse.

You might be wondering why there are no other Boolean operators that take a single argument. In order to understand why, you can look at a table that shows all theoretically possible Boolean operators that would take one argument:

Anot AIdentityYesNo
TrueFalseTrueTrueFalse
FalseTrueFalseTrueFalse

There are only four possible operators with one argument. Other thannot, the remaining three operators all have somewhat whimsical names since they don’t actually exist:

  • Identity: Since this operator simply returns its input, you could just delete it from your code with no effect.

  • Yes: This is a short-circuit operator since it doesn’t depend on its argument. You could just replace it withTrue and get the same result.

  • No: This is another short-circuit operator since it doesn’t depend on its argument. You could just replace it withFalse and get the same result.

None of the other possible operators with one argument would be useful.

Theand Boolean Operator

Theand operator takes two arguments. It evaluates toFalse unless both inputs areTrue. You could define the behavior ofand with the following truth table:

ABA and B
TrueTrueTrue
FalseTrueFalse
TrueFalseFalse
FalseFalseFalse

This table is verbose. However, it illustrates the same behavior as the description above. IfA isFalse, then the value ofB doesn’t matter. Because of this,and short-circuits if the first input isFalse. In other words, if the first input isFalse, then the second input isn’t evaluated.

The following code has a second input that has aside effect, printing, in order to provide a concrete example:

Python
>>>defprint_and_return(x):...print(f"I am returning{x}")...returnx...>>>Trueandprint_and_return(True)I am returning TrueTrue>>>Trueandprint_and_return(False)I am returning FalseFalse>>>Falseandprint_and_return(True)False>>>Falseandprint_and_return(False)False

In the last two cases, nothing is printed. The function isn’t called since calling it isn’t necessary to determine the value of theand operator. Being aware of short-circuits is important when expressions have a side effect. In the last two examples, the short-circuit evaluation prevents the printing side effect from happening.

One example in which this behavior can be crucial is in code that might raise exceptions:

Python
>>>definverse_and_true(n):...1//n...returnTrue...>>>inverse_and_true(5)True>>>inverse_and_true(0)Traceback (most recent call last):  File"<stdin>", line1, in<module>  File"<stdin>", line2, ininverse_and_trueZeroDivisionError:integer division or modulo by zero>>>Falseandinverse_and_true(0)False

The functioninverse_and_true() is admittedly silly, and manylinters would warn about the expression1 // n being useless. It does serve the purpose of neatly failing when given0 as a parameter since division by0 is invalid. However, the last line doesn’t raise an exception. Because of short-circuit evaluation, the function isn’t called, the division by0 doesn’t happen, and no exception is raised.

In contrast,True and inverse_and_true(0) would raise an exception. In that case, the value of the second input would be needed for the result ofand. Once the second input was evaluated,inverse_and_true(0) would be called, it would divide by0, and an exception would be raised.

Theor Boolean Operator

The value of theor operator isTrue unless both of its inputs areFalse. Theor operator could also be defined by the following truth table:

ABA or B
TrueTrueTrue
FalseTrueTrue
TrueFalseTrue
FalseFalseFalse

This table is verbose, but it has the same meaning as the explanation above.

When used informally, the wordor can have one of two meanings:

  • Theexclusiveor is howor is used in the phrase “You can file for an extension or submit your homework on time.” In this case, you can’t both file for an extension and submit your homework on time.

  • Theinclusiveor is sometimes indicated by using the conjunctionand/or. For example, “If you do well on this task, then you can get a raise and/or a promotion” means that you might get both a raise and a promotion.

When Python interprets the keywordor, it does so using the inclusiveor. If both inputs areTrue, then the result ofor isTrue.

Because it uses an inclusiveor, theor operator in Python also uses short-circuit evaluation. If the first argument isTrue, then the result isTrue, and there is no need to evaluate the second argument. The following examples demonstrate the short-circuit evaluation ofor:

Python
>>>defprint_and_true():...print("print_and_true called")...returnTrue...>>>Trueorprint_and_true()True>>>Falseorprint_and_true()print_and_true calledTrue

The second input isn’t evaluated byor unless the first one isFalse. In practice, the short-circuit evaluation ofor is used much less often than that ofand. However, it’s important to keep this behavior in mind when reading code.

Other Boolean Operators

The mathematical theory of Boolean logic determines that no other operators beyondnot,and, andor are needed. All other operators on two inputs can be specified in terms of these three operators. All operators on three or more inputs can be specified in terms of operators of two inputs.

In fact, even having bothor andand is redundant. Theand operator can be defined in terms ofnot andor, and theor operator can be defined in terms ofnot andand. However,and andor are so useful that all programming languages have both.

There are sixteen possible two-input Boolean operators. Except forand andor, they are rarely needed in practice. Because of this,True,False,not,and, andor are the only built-in Python Boolean operators.

Comparison Operators

Some ofPython’s operators check whether a relationship holds between two objects. Since the relationship either holds or doesn’t hold, these operators, calledcomparison operators, always return Boolean values.

Comparison operators are the most common source of Boolean values.

Equality and Inequality

The most common comparison operators are theequality operator (==) and theinequality operator (!=). It’s almost impossible to write any meaningful amount of Python code without using at least one of those operators.

The equality operator (==) is one of the most used operators in Python code. You often need to compare either an unknown result with a known result or two unknown results against each other. Some functions return values that need to be compared against asentinel to see if some edge condition has been detected. Sometimes you need to compare the results from two functions against each other.

The equality operator is often used to compare numbers:

Python
>>>1==1True>>>1==1.0True>>>1==2False

You may have usedequality operators before. They’re some of the most common operators in Python. For all built-in Python objects, and for most third-party classes, they return aBoolean value:True orFalse.

Note: The Python language doesn’t enforce that== and!= return Booleans. Libraries likeNumPy andpandas return other values.

Second only to the equality operator in popularity is theinequality operator (!=). It returnsTrue if the arguments aren’t equal andFalse if they are. The examples are similarly wide-ranging. Manyunit tests check that the value isn’t equal to a specific invalid value. A web client might check that the error code isn’t404 Not Found before trying an alternative.

Here are two examples of the Python inequality operator in use:

Python
>>>1!=2True>>>1!=(1+0.0)False

Perhaps the most surprising thing about the Python inequality operator is the fact that it exists in the first place. After all, you could achieve the same result as1 != 2 withnot (1 == 2). Python usually avoids extra syntax, and especially extra core operators, for things easily achievable by other means.

However, inequality is used so often that it was deemed worthwhile to have a dedicated operator for it. In old versions of Python, in the1.x series, there were actuallytwo different syntaxes.

As an April Fools’ joke, Python still supports an alternative syntax for inequality with the right__future__ import:

Python
>>>from__future__importbarry_as_FLUFL>>>1<>2True

Thisshould never be used in any code meant for real use. It could come in handy for your next Python trivia night, however.

Order Comparisons

Another set of test operators are theorder comparison operators. There are four order comparison operators that can be categorized by two qualities:

  • Direction: Is it less than or greater than?
  • Strictness: Is equality allowed or not?

Since the two choices are independent, you get2 * 2 == 4 order comparison operators. All four are listed in this table:

Less thanGreater than
Strict<>
Not strict<=>=

There are two options for direction and two options for strictness. This results in total of four order comparison operators.

The order comparison operators aren’t defined for all objects. Some objects don’t have a meaningful order. Even thoughlists and tuples are orderedlexicographically,dictionaries don’t have a meaningful order:

Python
>>>{1:3}<{2:4}Traceback (most recent call last):  File"<stdin>", line1, in<module>TypeError:'<' not supported between instances of 'dict' and 'dict'

It’s not obvious how dictionaries should be ordered. As per theZen of Python, in the face of ambiguity, Python refuses to guess.

Whilestrings andintegers are ordered separately, intertype comparisons aren’t supported:

Python
>>>1<="1"Traceback (most recent call last):  File"<stdin>", line1, in<module>TypeError:'<=' not supported between instances of 'int' and 'str'

Again, since there’s no obvious way to define order, Python refuses to compare them. This is similar to the addition operator (+). Though you can add strings to strings and integers to integers, adding strings to integers raises an exception.

When the order comparison operatorsare defined, in general they return a Boolean.

Note: Python doesn’t enforce that comparison operators return Booleans. While all built-in Python objects, and most third-party objects, return Booleans when compared, there are exceptions.

For example, comparison operators between NumPy arrays orpandas DataFrames return arrays and DataFrames. You’ll see more about the interaction of NumPy and Boolean values later in this tutorial.

Comparing numbers in Python is a common way of checking against boundary conditions. Note that< doesn’t allow equality, while<= does:

Python
>>>1<=1True>>>1<1False>>>2>3False>>>2>=2True

Programmers often use comparison operators without realizing that they return a Python Boolean value.

Theis Operator

Theis operator checks forobject identity. In other words,x is y evaluates toTrue only whenx andy evaluate to the same object. Theis operator has an opposite, theis not operator.

A typical usage ofis andis not is to compare lists for identity:

Python
>>>x=[]>>>y=[]>>>xisxTrue>>>xisnotxFalse>>>xisyFalse>>>xisnotyTrue

Even thoughx == y, they are not the same object. Theis not operator always returns the opposite ofis. There’s no difference between the expressionx is not y and the expressionnot (x is y) except for readability.

Keep in mind that the above examples show theis operator used only with lists. The behavior of theis operator onimmutable objects like numbers and strings ismore complicated.

Thein Operator

Thein operator checks formembership. An object can define what it considers members. Most sequences, such as lists, consider their elements to be members:

Python
>>>small_even=[2,4]>>>1insmall_evenFalse>>>2insmall_evenTrue>>>10insmall_evenFalse

Since2 is an element of the list,2 in small_even returnsTrue. Since1 and10 aren’t in the list, the other expressions returnFalse. In all cases, thein operator returns a Boolean value.

Since strings are sequences of characters, you might expect them to also check for membership. In other words, characters that are members of the string will returnTrue forin, while those that don’t will returnFalse:

Python
>>>"e"in"hello beautiful world"True>>>"x"in"hello beautiful world"False

Since"e" is the second element of the string, the first example returnsTrue. Sincex doesn’t appear in the string, the second example returnsFalse. However, along with individual characters, substrings are also considered to be members of a string:

Python
>>>"beautiful"in"hello beautiful world"True>>>"belle"in"hello beautiful world"False

Since"beautiful" is a substring, thein operator returnsTrue. Since"belle" is not a substring, thein operator returnsFalse. This is despite the fact that every individual letter in"belle" is a member of the string.

Like the operatorsis and==, thein operator also has an opposite,not in. You can usenot in to confirm that an element is not a member of an object.

Chaining Comparison Operators

Comparison operators can formchains. You can create comparison operator chains by separating expressions with comparison operators to form a larger expression:

Python
>>>1<2<3True

The expression1 < 2 < 3 is a comparison operator chain. It has expressions separated by comparison operators. The result isTrue because both parts of the chain areTrue. You can break up the chain to see how it works:

Python
>>>1<2and2<3True

Since1 < 2 returnsTrue and2 < 3 returnsTrue,and returnsTrue. A comparison chain is equivalent to usingand on all its links. In this case, sinceTrue and True returnsTrue, the result of the whole chain isTrue. This means that if any of the links areFalse, then the whole chain isFalse:

Python
>>>1<3<2False

This comparison chain returnsFalse since not all of its links areTrue. Because comparison chains are an implicitand operator, if even one link isFalse, then the whole chain isFalse. You can break up the chain to see how it works:

Python
>>>1<3and3<2False

In this case, the parts of the chain evaluate to the following Booleans:

  • 1 < 3 isTrue
  • 3 < 2 isFalse

This means that one of the results isTrue and one isFalse. SinceTrue and False is equal toFalse, the value of the entire chain isFalse.

You can mix types and operations in a comparison chain as long as the types can be compared:

Python
>>>1<2<1False>>>1==1.0<0.5False>>>1==1.0==TrueTrue>>>1<3>2True>>>1<2<3<4<5True

The operators don’t have to be all the same. Not even the types have to be all the same. In the examples above, you have three numeric types:

  1. int
  2. float
  3. bool

These are three different numeric types, but you can compare objects of different numeric types without issue.

Short-Circuit Chain Evaluation

If chains use an implicitand, then chains must also short-circuit. This is important because even in cases where an order comparison isn’t defined, it’s possible for a chain to returnFalse:

Python
>>>2<"2"Traceback (most recent call last):  File"<stdin>", line1, in<module>TypeError:'<' not supported between instances of 'int' and 'str'>>>3<2<"2"False

Even though Python can’t order-compare integers and strings numbers,3 < 2 < "2" evaluates toFalse because it doesn’t evaluate the second comparison. In this case, the short-circuit evaluation prevents another side effect: raising an exception.

Short-circuit evaluation of comparison chains can prevent other exceptions:

Python
>>>3<2<(1//0)False

Dividing1 by0 would have raised aZeroDivisionError. However, because of the short-circuit evaluation, Python doesn’t evaluate the invalid division. This means that Python skips evaluating not only the comparison but also the inputs to the comparison.

Another aspect that is important to understand about comparison chains is that when Pythondoes evaluate an element in the chain, it evaluates it only once:

Python
>>>deffoo():...print("I'm foo")...return1...>>>0<foo()<2I'm fooTrue>>>(0<foo())and(foo()<2)I'm fooI'm fooTrue

Because the middle elements are evaluated only once, it’s not always safe to refactorx < y < z to(x < y) and (y < z). Although the chain behaves likeand in its short-circuit evaluation, it evaluates all values, including the intermediate ones, only once.

Chains are especially useful forrange checks, which confirm that a value falls within a given range. For example, in a daily invoice that includes the number hours worked, you might do the following:

Python
>>>hours_worked=5>>>1<=hours_worked<=25True

If there are0 hours worked, then there’s no reason to send the invoice. Accounting for Daylight Saving Time, the maximum number of hours in a day is25. The above range check confirms that the number of hours worked in a day falls within the allowable range.

Mixing Operators and Chaining

Until now, all our examples involved==,!=, and the order comparisons. However, you can chain all of Python’s comparison operators. This can lead to surprising behavior:

Python
>>>a=0>>>aisa<1True>>>(aisa)<1False>>>ais(a<1)False

Becausea is a < 1 is a comparison chain, it evaluates toTrue. You can break the chain into its parts:

  • The expressiona is a isTrue, as it would be for any value evaluated against itself.
  • The expressiona < 1 isTrue since0 is less than1.

Since both parts areTrue, the chain evaluates toTrue.

However, people who are used to other operators in Python may assume that, like other expressions involving multiple operators such as1 + 2 * 3, Python inserts parentheses into to the expression. However, neither way of inserting parenthesis will evaluate toTrue.

You can see why both evaluate toFalse if you break up the expressions. If you break up the first expression, you get the following:

Python
>>>a=0>>>aisaTrue>>>True==1True>>>(aisa)<1False

You can see above thata is a returnsTrue, as it would for any value. This means that(a is a) < 1 is the same asTrue < 1. Booleans are numeric types, andTrue is equal to1. SoTrue < 1 is the same as1 < 1. Since this is astrict inequality, and1 == 1, it returns False.

The second expression works differently:

Python
>>>a=0False>>>a<1True>>>0isTrue<stdin>:1: SyntaxWarning: "is" with a literal. Did you mean "=="?False

Since0 is less than1,a < 1 returnsTrue. Since0 != True, then it can’t be the case that0 is True.

Note: Don’t take the aboveSyntaxWarning lightly. Usingis on numbers can beconfusing. However, specifically for cases in which you know the numbers arenot equal, you can know thatis will also returnFalse. While this example is correct, it’s not an example of good Python coding style.

The most important lesson to draw from this is that chaining comparisons withis usually isn’t a good idea. It confuses the reader and probably isn’t necessary.

Likeis, thein operator and its opposite,not in, can often yield surprising results when chained:

Python
>>>"b"in"aba"in"cabad"<"cabae"True

To maximize the confusion, this example chains comparisons with different operators and usesin with strings to check for substrings. Again, this is not an example of well-written code! However, it’s important to be able to read this example and understand why it returnsTrue.

Finally, you can chainis not withnot in:

Python
>>>greeting="hello">>>quality="good">>>end_greeting="farewell">>>greetingisnotqualitynotinend_greetingTrue

Note that the order ofnot in the two operators isn’t the same! The negative operators areis not andnot in. This corresponds with the regular usage in English, but it’s easy to make a mistake when modifying code.

Python Boolean Testing

The most popular use for a Python Boolean is in anif statement. This statement will execute if the value isTrue:

Python
>>>1==1True>>>if1==1:...print("yep")...yep>>>1==2False>>>if1==2:...print("yep")...

print() is called only when the expression evaluates toTrue. However, in Python you can give any value toif. The values thatif considersTrue are calledtruthy, and the values thatif considersFalse are calledfalsy.

if decides which values are truthy and which are falsy by internally calling the built-inbool(). You’ve already encounteredbool() as the Python Boolean type. When called, it converts objects to Booleans.

None as a Boolean Value

The singleton objectNone is always falsy:

Python
>>>bool(None)False

This is often useful inif statements that check for a sentinel value. However, it’s usually better to explicitly check for identity withis None. SometimesNone can be useful in combination with short-circuit evaluation in order to have a default.

For example, you can useor to substituteNone with an empty list:

Python
>>>defadd_num_and_len(num,things=None):...returnnum+len(thingsor[])...>>>add_num_and_len(5,[1,2,3])8>>>add_num_and_len(6)6

In this example, the list won’t be created ifthings is a non-empty list sinceor will short-circuit before it evaluates[].

Numbers as Boolean Values

For numbers,bool(x) is equivalent tox != 0. This means the only falsy integer is0:

Python
>>>bool(3),bool(-5),bool(0)(True, True, False)

All nonzero integers are truthy. This is also true forfloating-point numbers, including special floating-point numbers likeinfinity andNot a Number (NaN):

Python
>>>importmath>>>[bool(x)forxin[0,1.2,0.5,math.inf,math.nan]][False, True, True, True, True]

Since infinity and NaN aren’t equal to0, they’re truthy.

Equality and inequality comparisons on floating-point numbers are subtle operations. Since doingbool(x) is equivalent tox != 0, this can lead to surprising results for floating-point numbers:

Python
>>>bool(0.1+0.2+(-0.2)+(-0.1))True>>>0.1+0.2+(-0.2)+(-0.1)2.7755575615628914e-17

Floating-point number computations can be inexact. Because of that, the results ofbool() on floating-point numbers can be surprising.

Python has more numeric types in the standard library, and they follow the same rules. For non-built-in numeric types,bool(x) is also equivalent tox != 0. Thefractions module is in the standard library. Like other numeric types, the only falsy fraction is0/1:

Python
>>>importfractions>>>bool(fractions.Fraction("1/2")),bool(fractions.Fraction("0/1"))(True, False)

As with integers and floating-point numbers, fractions are false only when they’re equal to0.

Thedecimal module is also in the standard library. Decimals are similarly falsy only when they’re equal to0:

Python
>>>importdecimal,math>>>withdecimal.localcontext(decimal.Context(prec=3))asctx:...bool(ctx.create_decimal(math.pi)-ctx.create_decimal(22)/7)...False>>>withdecimal.localcontext(decimal.Context(prec=4))asctx:...bool(ctx.create_decimal(math.pi)-ctx.create_decimal(22)/7)...True

The number22 / 7 is an approximation of Pi to two decimal places. This fact was discussed byArchimedes in the 3rd century BCE. When the difference between22 / 7 and Pi is computed with this precision, the result is falsy. When the difference is computed with higher precision, the difference isn’t equal to0, and so is truthy.

Sequences as Boolean Values

In general, objects that have alen() will be falsy when the result oflen() is0. It doesn’t matter if they’re lists, tuples, sets, strings, or byte strings:

Python
>>>bool([1]),bool([])(True, False)>>>bool((1,2)),bool(())(True, False)>>>bool({1,2,3}),bool(set())(True, False)>>>bool({1:2}),bool({})(True, False)>>>bool("hello"),bool("")(True, False)>>>bool(b"xyz"),bool(b"")(True, False)

All built-in Python objects that have a length follow this rule. Later, you’ll see some exceptions to this rule for non-built-in objects.

Other Types as Boolean Values

Unless types have alen() or specifically define whether they’re truthy or falsy, they’re always truthy. This is true for built-in as well as user-defined types. In particular, functions are always truthy:

Python
>>>deffunc():...pass...>>>bool(func)True

Methods are always truthy, too. You might encounter this if a parenthesis is missing when you call a function or method:

Python
>>>importdatetime>>>defbefore_noon():...returndatetime.datetime.now().hour<12...>>>defgreet():...ifbefore_noon:...print("Good morning!")...else:...print("Good evening!")...>>>greet()Good morning!>>>datetime.datetime.now().hour20

This can happen as a result of a forgotten parenthesis or misleading documentation that doesn’t mention that you need to call the function. If you expect a Python Boolean value but have a function that returns a Boolean value, then it will always be truthy.

By default, user-defined types are always truthy:

Python
>>>classDummy:...pass...>>>bool(Dummy())True

Creating an empty class makes every object of that class truthy. All objects are truthy unlessspecial methods are defined. If you want to make some instances of your class falsy, you can define.__bool__():

Python
>>>classBoolLike:...am_i_truthy=False...def__bool__(self):...returnself.am_i_truthy...>>>x=BoolLike()>>>bool(x)False>>>x.am_i_truthy=True>>>bool(x)True

You can also use.__bool__() to make an object neither truthy nor falsy:

Python
>>>classExcludedMiddle:...def__bool__(self):...raiseValueError("neither")...>>>x=ExcludedMiddle()>>>bool(x)Traceback (most recent call last):  File"<stdin>", line1, in<module>  File"<stdin>", line3, in__bool__ValueError:neither>>>ifx:...print("x is truthy")...else:...print("x is falsy")...Traceback (most recent call last):  File"<stdin>", line1, in<module>  File"<stdin>", line3, in__bool__ValueError:neither

Theif statement also uses.__bool__(). It does so to evaluate whether the object is truthy or falsy, which determines which branch to execute.

If you define the__len__ method on a class, then its instances have alen(). In that case, the Boolean value of the instances will be falsy exactly when their length is0:

Python
>>>classDummyContainer:...my_length=0...def__len__(self):...returnself.my_length...>>>x=DummyContainer()>>>bool(x)False>>>x.my_length=5>>>bool(x)True

In this example,len(x) would return0 before the assignment and5 afterward. The reverse, however, is not true. Defining.__bool__() doesn’t give instances a length:

Python
>>>classAlwaysTrue:...def__bool__(self):...returnTrue...>>>classAlwaysFalse:...def__bool__(self):...returnFalse...>>>bool(AlwaysTrue()),bool(AlwaysFalse())(True, False)>>>len(AlwaysTrue())Traceback (most recent call last):  File"<stdin>", line1, in<module>TypeError:object of type 'AlwaysTrue' has no len()>>>len(AlwaysFalse())Traceback (most recent call last):  File"<stdin>", line1, in<module>TypeError:object of type 'AlwaysFalse' has no len()

Defining.__bool__() doesn’t make instances of either class have alen(). When both.__bool__() and.__len__() are defined,.__bool__() takes precedence:

Python
>>>classBooleanContainer:...def__len__(self):...return100...def__bool__(self):...returnFalse...>>>x=BooleanContainer()>>>len(x)100>>>bool(x)False

Even thoughx has a length of100, it’s still falsy.

Example: NumPy Arrays

The above example may seem like something that only happens when you write a class intended to demonstrate edge cases in Python. However, it’s possible to get similar results using one of the most popular libraries onPyPI:NumPy.

Arrays, like numbers, are falsy or truthy depending on how they compare to0:

Python
>>>fromnumpyimportarray>>>x=array([0])>>>len(x)1>>>bool(x)False

Even thoughx has a length of1, it’s still falsy because its value is0.

When arrays have more than one element, some elements might be falsy and some might be truthy. In those cases, NumPy will raise an exception:

Python
>>>fromnumpyimportarray>>>importtextwrap>>>y=array([0,1])>>>try:...bool(y)...exceptValueErrorasexc:...print("\n".join(textwrap.wrap(str(exc))))...The truth value of an array with more than one element is ambiguous.Use a.any() or a.all()

The exception is so wordy that in order to make it easy to read, the code uses text processing to wrap the lines.

An even more interesting edge case involves empty arrays. You might wonder if those are falsy like other sequences or truthy because they’re not equal to0. As you saw above, those aren’t the only two possible answers. The arrays could also refuse to have a Boolean value.

Interestingly, none of these options is entirely true:

Python
>>>bool(array([]))<stdin>:1: DeprecationWarning: The truth value of an empty array is ambiguous.Returning False, but in future this will result in an error.Use `array.size > 0` to check that an array is not empty.False

While empty arrays arecurrently falsy, relying on this behavior is dangerous. In some future NumPy version, this will raise an exception.

Operators and Functions

There are a few more places in Python where Boolean testing takes place. One of those is in Boolean operators.

The operatorsand,or, andnot accept any value that supports Boolean testing. In the case ofnot, it will always return a Boolean value:

Python
>>>not1False>>>not0True

The truth table fornot is still correct, but now it takes the truthiness of the input.

In the case ofand andor, in addition to short-circuit evaluation, they also return the value at which they stopped evaluating:

Python
>>>1and22>>>0and10>>>1or21>>>0or22

The truth tables are still correct, but they now define the truthiness of the results, which depends on the truthiness of the inputs. This can come handy when, for example, you want to give values defaults.

Assume you have a function calledsummarize() that, if the text is too long, takes the beginning and the end and adds an ellipsis (...) in the middle. This might be useful in some reports that can’t fit the full text. However, some datasets have missing values represented byNone.

Sincesummarize() assumes the input is a string, it will fail onNone:

Python
>>>defsummarize(long_text):...iflen(long_text)<=4:...returnlong_text...returnlong_text[:2]+"..."+long_text[-2:]...>>>summarize("hello world")'he...ld'>>>summarize("hi")'hi'>>>summarize("")''>>>summarize(None)Traceback (most recent call last):  File"<stdin>", line1, in<module>  File"<stdin>", line2, insummarizeTypeError:object of type 'NoneType' has no len()>>>forain["hello world","hi","",None]:...print("-->",summarize(aor""))...--> he...ld--> hi-->-->

This example takes advantage of the falsiness ofNone and the fact thator not only short-circuits but also returns the last value to be evaluated. The code for printing the report addsor "" to the argument tosummarize(). The addition ofor "" helps you to avoid errors with just a small code change.

The built-in functionsall() andany() evaluate truthiness and also short-circuit, but they don’t return the last value to be evaluated.all() checks whether all of its arguments are truthy:

Python
>>>all([1,2,3])True>>>all([0,1,2])False>>>all(x/(x-1)forxin[0,1])False

In the last line,all() doesn’t evaluatex / (x - 1) for1. Since1 - 1 is0, this would have raised aZeroDivisionError.

any() checks whether any of its arguments are truthy:

Python
>>>any([1,0,0])True>>>any([False,0,0.0])False>>>any(1/xforxin[1,0])True

In the last line,any() doesn’t evaluate1 / x for0.

Conclusion

The Python Boolean is a commonly used data type with many useful applications. You can use Booleans with operators likenot,and,or,in,is,==, and!= to compare values and check for membership, identity, or equality. You can also use Boolean testing with anif statement to control the flow of your programs based on the truthiness of an expression.

In this tutorial, you’ve learned how to:

  • Manipulate Boolean values withBoolean operators
  • Convert Booleans toother types
  • Convert other types toPython Booleans
  • Use Booleans to writeefficient and readable Python code

You now know how short-circuit evaluation works and recognize the connection between Booleans and theif statement. This knowledge will help you to both understand existing code and avoid common pitfalls that can lead to errors in your own programs.

Watch Now This tutorial has a related video course created by the Real Python team. Watch it together with the written tutorial to deepen your understanding:Python Booleans: Leveraging the Values of Truth

🐍 Python Tricks 💌

Get a short & sweetPython Trick delivered to your inbox every couple of days. No spam ever. Unsubscribe any time. Curated by the Real Python team.

Python Tricks Dictionary Merge

AboutMoshe Zadka

Moshe has been using Python since 1998. He has contributed to CPython, and is a founding member of the Twisted project. He has been teaching Python in various venues since 2002.

» More about Moshe

Each tutorial at Real Python is created by a team of developers so that it meets our high quality standards. The team members who worked on this tutorial are:

MasterReal-World Python Skills With Unlimited Access to Real Python

Locked learning resources

Join us and get access to thousands of tutorials, hands-on video courses, and a community of expert Pythonistas:

Level Up Your Python Skills »

MasterReal-World Python Skills
With Unlimited Access to Real Python

Locked learning resources

Join us and get access to thousands of tutorials, hands-on video courses, and a community of expert Pythonistas:

Level Up Your Python Skills »

What Do You Think?

Rate this article:

What’s your #1 takeaway or favorite thing you learned? How are you going to put your newfound skills to use? Leave a comment below and let us know.

Commenting Tips: The most useful comments are those written with the goal of learning from or helping out other students.Get tips for asking good questions andget answers to common questions in our support portal.


Looking for a real-time conversation? Visit theReal Python Community Chat or join the next“Office Hours” Live Q&A Session. Happy Pythoning!

Keep Learning

Related Topics:intermediatepython

Recommended Video Course:Python Booleans: Leveraging the Values of Truth

Related Tutorials:

Keep reading Real Python by creating a free account or signing in:

Already have an account?Sign-In

Almost there! Complete this form and click the button below to gain instant access:

Python Logo

5 Thoughts On Python Mastery

🔒 No spam. We take your privacy seriously.


[8]ページ先頭

©2009-2025 Movatter.jp