-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathPython Operators 1
More file actions
1285 lines (916 loc) · 71 KB
/
Python Operators 1
File metadata and controls
1285 lines (916 loc) · 71 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
Getting Started With Operators and Expressions
The Assignment Operator and Statements
Arithmetic Operators and Expressions in Python
Comparison Operators and Expressions in Python
Comparison of Integer Values
Comparison of Floating-Point Values
Comparison of Strings
Comparison of Lists and Tuples
Boolean Operators and Expressions in Python
Boolean Expressions Involving Boolean Operands
Evaluation of Regular Objects in a Boolean Context
Boolean Expressions Involving Other Types of Operands
Compound Logical Expressions and Short-Circuit Evaluation
Idioms That Exploit Short-Circuit Evaluation
Compound vs Chained Expressions
Conditional Expressions or the Ternary Operator
Identity Operators and Expressions in Python
Membership Operators and Expressions in Python
Concatenation and Repetition Operators and Expressions
The Walrus Operator and Assignment Expressions
Bitwise Operators and Expressions in Python
Operator Precedence in Python
Augmented Assignment Operators and Expressions
Conclusion
Frequently Asked Questions
Remove ads
Python operators enable you to perform computations by combining objects and operators into expressions. Understanding Python operators is essential for manipulating data effectively.
This tutorial covers arithmetic, comparison, Boolean, identity, membership, bitwise, concatenation, and repetition operators, along with augmented assignment operators. You’ll also learn how to build expressions using these operators and explore operator precedence to understand the order of operations in complex expressions.
By the end of this tutorial, you’ll understand that:
Arithmetic operators perform mathematical calculations on numeric values.
Comparison operators evaluate relationships between values, returning Boolean results.
Boolean operators create compound logical expressions.
Identity operators determine if two operands refer to the same object.
Membership operators check for the presence of a value in a container.
Bitwise operators manipulate data at the binary level.
Concatenation and repetition operators manipulate sequence data types.
Augmented assignment operators simplify expressions involving the same variable.
This tutorial provides a comprehensive guide to Python operators, empowering you to create efficient and effective expressions in your code. To get the most out of this tutorial, you should have a basic understanding of Python programming concepts, such as variables, assignments, and built-in data types.
Free Bonus: Click here to download your comprehensive cheat sheet covering the various operators in Python.
Take the Quiz: Test your knowledge with our interactive “Python Operators and Expressions” quiz. You’ll receive a score upon completion to help you track your learning progress:
Operators and Expressions in Python
Interactive Quiz
Python Operators and Expressions
Test your understanding of Python operators and expressions.
Getting Started With Operators and Expressions
In programming, an operator is usually a symbol or combination of symbols that allows you to perform a specific operation. This operation can act on one or more operands. If the operation involves a single operand, then the operator is unary. If the operator involves two operands, then the operator is binary.
For example, in Python, you can use the minus sign (-) as a unary operator to declare a negative number. You can also use it to subtract two numbers:
>>> -273.15
-273.15
>>> 5 - 2
3
In this code snippet, the minus sign (-) in the first example is a unary operator, and the number 273.15 is the operand. In the second example, the same symbol is a binary operator, and the numbers 5 and 2 are its left and right operands.
Programming languages typically have operators built in as part of their syntax. In many languages, including Python, you can also create your own operator or modify the behavior of existing ones, which is a powerful and advanced feature to have.
In practice, operators provide a quick shortcut for you to manipulate data, perform mathematical calculations, compare values, run Boolean tests, assign values to variables, and more. In Python, an operator may be a symbol, a combination of symbols, or a keyword, depending on the type of operator that you’re dealing with.
For example, you’ve already seen the subtraction operator, which is represented with a single minus sign (-). The equality operator is a double equal sign (==). So, it’s a combination of symbols:
>>> 42 == 42
True
In this example, you use the Python equality operator (==) to compare two numbers. As a result, you get True, which is one of Python’s Boolean values.
Speaking of Boolean values, the Boolean or logical operators in Python are keywords rather than signs, as you’ll learn in the section about Boolean operators and expressions. So, instead of the odd signs like ||, &&, and ! that many other programming languages use, Python uses or, and, and not.
Using keywords instead of odd signs is a really cool design decision that’s consistent with the fact that Python loves and encourages code’s readability.
You’ll find several categories or groups of operators in Python. Here’s a quick list of those categories:
Assignment operators
Arithmetic operators
Comparison operators
Boolean or logical operators
Identity operators
Membership operators
Concatenation and repetition operators
Bitwise operators
All these types of operators take care of specific types of computations and data-processing tasks. You’ll learn more about these categories throughout this tutorial. However, before jumping into more practical discussions, you need to know that the most elementary goal of an operator is to be part of an expression. Operators by themselves don’t do much:
>>> -
File "<input>", line 1
-
^
SyntaxError: incomplete input
>>> ==
File "<input>", line 1
==
^^
SyntaxError: incomplete input
>>> or
File "<input>", line 1
or
^^
SyntaxError: incomplete input
As you can see in this code snippet, if you use an operator without the required operands, then you’ll get a syntax error. So, operators must be part of expressions, which you can build using Python objects as operands.
So, what is an expression anyway? Python has simple and compound statements. A simple statement is a construct that occupies a single logical line, like an assignment statement. A compound statement is a construct that occupies multiple logical lines, such as a for loop or a conditional statement. An expression is a simple statement that produces and returns a value.
You’ll find operators in many expressions. Here are a few examples:
>>> 7 + 5
12
>>> 42 / 2
21.0
>>> 5 == 5
True
In the first two examples, you use the addition and division operators to construct two arithmetic expressions whose operands are integer numbers. In the last example, you use the equality operator to create a comparison expression. In all cases, you get a specific value after executing the expression.
Note that not all expressions use operators. For example, a bare function call is an expression that doesn’t require any operator:
>>> abs(-7)
7
>>> pow(2, 8)
256
>>> print("Hello, World!")
Hello, World!
In the first example, you call the built-in abs() function to get the absolute value of -7. Then, you compute 2 to the power of 8 using the built-in pow() function. These function calls occupy a single logical line and return a value. So, they’re expressions.
Finally, the call to the built-in print() function is another expression. This time, the function doesn’t return a fruitful value, but it still returns None, which is the Python null type. So, the call is technically an expression.
Note: All Python functions have a return value, either explicit or implicit. If you don’t provide an explicit return statement when defining a function, then Python will automatically make the function return None.
Even though all expressions are statements, not all statements are expressions. For example, pure assignment statements don’t return any value, as you’ll learn in a moment. Therefore, they’re not expressions. The assignment operator is a special operator that doesn’t create an expression but a statement.
Note: Since version 3.8, Python also has what it calls assignment expressions. These are special types of assignments that do return a value. You’ll learn more about this topic in the section The Walrus Operator and Assignment Expressions.
Okay! That was a quick introduction to operators and expressions in Python. Now it’s time to dive deeper into the topic. To kick things off, you’ll start with the assignment operator and statements.
Remove ads
The Assignment Operator and Statements
The assignment operator is one of the most frequently used operators in Python. The operator consists of a single equal sign (=), and it operates on two operands. The left-hand operand is typically a variable, while the right-hand operand is an expression.
Note: As you already learned, the assignment operator doesn’t create an expression. Instead, it creates a statement that doesn’t return any value.
The assignment operator allows you to assign values to variables. Strictly speaking, in Python, this operator makes variables or names refer to specific objects in your computer’s memory. In other words, an assignment creates a reference to a concrete object and attaches that reference to the target variable.
Note: To dive deeper into using the assignment operator, check out Python’s Assignment Operator: Write Robust Assignments.
For example, all the statements below create new variables that hold references to specific objects:
>>> number = 42
>>> day = "Friday"
>>> digits = (0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
>>> letters = ["a", "b", "c"]
In the first statement, you create the number variable, which holds a reference to the number 42 in your computer’s memory. You can also say that the name number points to 42, which is a concrete object.
In the rest of the examples, you create other variables that point to other types of objects, such as a string, tuple, and list, respectively.
You’ll use the assignment operator in many of the examples that you’ll write throughout this tutorial. More importantly, you’ll use this operator many times in your own code. It’ll be your forever friend. Now you can dive into other Python operators!
Arithmetic Operators and Expressions in Python
Arithmetic operators are those operators that allow you to perform arithmetic operations on numeric values. Yes, they come from math, and in most cases, you’ll represent them with the usual math signs. The following table lists the arithmetic operators that Python currently supports:
Operator Type Operation Sample Expression Result
+ Unary Positive +a a without any transformation since this is simply a complement to negation
+ Binary Addition a + b The arithmetic sum of a and b
- Unary Negation -a The value of a but with the opposite sign
- Binary Subtraction a - b b subtracted from a
* Binary Multiplication a * b The product of a and b
/ Binary Division a / b The quotient of a divided by b, expressed as a float
% Binary Modulo a % b The remainder of a divided by b
// Binary Floor division or integer division a // b The quotient of a divided by b, rounded to the next smallest whole number
** Binary Exponentiation a**b a raised to the power of b
Note that a and b in the Sample Expression column represent numeric values, such as integer, floating-point, complex, rational, and decimal numbers.
Here are some examples of these operators in use:
>>> a = 5
>>> b = 2
>>> +a
5
>>> -b
-2
>>> a + b
7
>>> a - b
3
>>> a * b
10
>>> a / b
2.5
>>> a % b
1
>>> a // b
2
>>> a**b
25
In this code snippet, you first create two new variables, a and b, holding 5 and 2, respectively. Then you use these variables to create different arithmetic expressions using a specific operator in each expression.
Note: The Python REPL will display the return value of an expression as a way to provide immediate feedback to you. So, when you’re in an interactive session, you don’t need to use the print() function to check the result of an expression. You can just type in the expression and press Enter to get the result.
Again, the standard division operator (/) always returns a floating-point number, even if the dividend is evenly divisible by the divisor:
>>> 10 / 5
2.0
>>> 10.0 / 5
2.0
In the first example, 10 is evenly divisible by 5. Therefore, this operation could return the integer 2. However, it returns the floating-point number 2.0. In the second example, 10.0 is a floating-point number, and 5 is an integer. In this case, Python internally promotes 5 to 5.0 and runs the division. The result is a floating-point number too.
Note: With complex numbers, the division operator doesn’t return a floating-point number but a complex one:
>>> 10 / 5j
-2j
Here, you run a division between an integer and a complex number. In this case, the standard division operator returns a complex number.
Finally, consider the following examples of using the floor division (//) operator:
>>> 10 // 4
2
>>> -10 // -4
2
>>> 10 // -4
-3
>>> -10 // 4
-3
Floor division always rounds down. This means that the result is the greatest integer that’s smaller than or equal to the quotient. For positive numbers, it’s as though the fractional portion is truncated, leaving only the integer portion.
Remove ads
Comparison Operators and Expressions in Python
The Python comparison operators allow you to compare numerical values and any other objects that support them. The table below lists all the currently available comparison operators in Python:
Operator Operation Sample Expression Result
== Equal to a == b • True if the value of a is equal to the value of b
• False otherwise
!= Not equal to a != b • True if a isn’t equal to b
• False otherwise
< Less than a < b • True if a is less than b
• False otherwise
<= Less than or equal to a <= b • True if a is less than or equal to b
• False otherwise
> Greater than a > b • True if a is greater than b
• False otherwise
>= Greater than or equal to a >= b • True if a is greater than or equal to b
• False otherwise
The comparison operators are all binary. This means that they require left and right operands. These operators always return a Boolean value (True or False) that depends on the truth value of the comparison at hand.
Note that comparisons between objects of different data types often don’t make sense and sometimes aren’t allowed in Python. For example, you can compare a number and a string for equality with the == operator. However, you’ll get False as a result:
>>> 2 == "2"
False
The integer 2 isn’t equal to the string "2". Therefore, you get False as a result. You can also use the != operator in the above expression, in which case you’ll get True as a result.
Non-equality comparisons between operands of different data types raise a TypeError exception:
>>> 5 < "7"
Traceback (most recent call last):
...
TypeError: '<' not supported between instances of 'int' and 'str'
In this example, Python raises a TypeError exception because a less than comparison (<) doesn’t make sense between an integer and a string. So, the operation isn’t allowed.
It’s important to note that in the context of comparisons, integer and floating-point values are compatible, and you can compare them.
You’ll typically use and find comparison operators in Boolean contexts like conditional statements and while loops. They allow you to make decisions and define a program’s control flow.
The comparison operators work on several types of operands, such as numbers, strings, tuples, and lists. In the following sections, you’ll explore the differences.
Comparison of Integer Values
Probably, the more straightforward comparisons in Python and in math are those involving integer numbers. They allow you to count real objects, which is a familiar day-to-day task. In fact, the non-negative integers are also called natural numbers. So, comparing this type of number is probably pretty intuitive, and doing so in Python is no exception.
Consider the following examples that compare integer numbers:
>>> a = 10
>>> b = 20
>>> a == b
False
>>> a != b
True
>>> a < b
True
>>> a <= b
True
>>> a > b
False
>>> a >= b
False
>>> x = 30
>>> y = 30
>>> x == y
True
>>> x != y
False
>>> x < y
False
>>> x <= y
True
>>> x > y
False
>>> x >= y
True
In the first set of examples, you define two variables, a and b, to run a few comparisons between them. The value of a is less than the value of b. So, every comparison expression returns the expected Boolean value. The second set of examples uses two values that are equal, and again, you get the expected results.
Comparison of Floating-Point Values
Comparing floating-point numbers is a bit more complicated than comparing integers. The value stored in a float object may not be precisely what you’d think it would be. For that reason, it’s bad practice to compare floating-point values for exact equality using the == operator.
Consider the example below:
>>> x = 1.1 + 2.2
>>> x == 3.3
False
>>> 1.1 + 2.2
3.3000000000000003
Yikes! The internal representation of this addition isn’t exactly equal to 3.3, as you can see in the final example. So, comparing x to 3.3 with the equality operator returns False.
To compare floating-point numbers for equality, you need to use a different approach. The preferred way to determine whether two floating-point values are equal is to determine whether they’re close to one another, given some tolerance.
The math module from the standard library provides a function conveniently called isclose() that will help you with float comparison. The function takes two numbers and tests them for approximate equality:
>>> from math import isclose
>>> x = 1.1 + 2.2
>>> isclose(x, 3.3)
True
In this example, you use the isclose() function to compare x and 3.3 for approximate equality. This time, you get True as a result because both numbers are close enough to be considered equal.
For further details on using isclose(), check out the Find the Closeness of Numbers With Python isclose() section in The Python math Module: Everything You Need to Know.
Remove ads
Comparison of Strings
You can also use the comparison operators to compare Python strings in your code. In this context, you need to be aware of how Python internally compares string objects. In practice, Python compares strings character by character using each character’s Unicode code point. Unicode is Python’s default character set.
You can use the built-in ord() function to learn the Unicode code point of any character in Python. Consider the following examples:
>>> ord("A")
65
>>> ord("a")
97
>>> "A" == "a"
False
>>> "A" > "a"
False
>>> "A" < "a"
True
The uppercase "A" has a lower Unicode point than the lowercase "a". So, "A" is less than "a". In the end, Python compares characters using integer numbers. So, the same rules that Python uses to compare integers apply to string comparison.
When it comes to strings with several characters, Python runs the comparison character by character in a loop.
The comparison uses lexicographical ordering, which means that Python compares the first item from each string. If their Unicode code points are different, this difference determines the comparison result. If the Unicode code points are equal, then Python compares the next two characters, and so on, until either string is exhausted:
>>> "Hello" > "HellO"
True
>>> ord("o")
111
>>> ord("O")
79
In this example, Python compares both operands character by character. When it reaches the end of the string, it compares "o" and "O". Because the lowercase letter has a greater Unicode code point, the first version of the string is greater than the second.
You can also compare strings of different lengths:
>>> "Hello" > "Hello, World!"
False
In this example, Python runs a character-by-character comparison as usual. If it runs out of characters, then the shorter string is less than the longer one. This also means that the empty string is the smallest possible string.
Comparison of Lists and Tuples
In your Python journey, you can also face the need to compare lists with other lists and tuples with other tuples. These data types also support the standard comparison operators. Like with strings, when you use a comparison operator to compare two lists or two tuples, Python runs an item-by-item comparison.
Note that Python applies specific rules depending on the type of the contained items. Here are some examples that compare lists and tuples of integer values:
>>> [2, 3] == [2, 3]
True
>>> (2, 3) == (2, 3)
True
>>> [5, 6, 7] < [7, 5, 6]
True
>>> (5, 6, 7) < (7, 5, 6)
True
>>> [4, 3, 2] < [4, 3, 2]
False
>>> (4, 3, 2) < (4, 3, 2)
False
In these examples, you compare lists and tuples of numbers using the standard comparison operators. When comparing these data types, Python runs an item-by-item comparison.
For example, in the first expression above, Python compares the 2 in the left operand and the 2 in the right operand. Because they’re equal, Python continues comparing 3 and 3 to conclude that both lists are equal. The same thing happens in the second example, where you compare tuples containing the same data.
It’s important to note that you can actually compare lists to tuples using the == and != operators. However, you can’t compare lists and tuples using the <, >, <=, and >= operators:
>>> [2, 3] == (2, 3)
False
>>> [2, 3] != (2, 3)
True
>>> [2, 3] > (2, 3)
Traceback (most recent call last):
...
TypeError: '>' not supported between instances of 'list' and 'tuple'
>>> [2, 3] <= (2, 3)
Traceback (most recent call last):
...
TypeError: '<=' not supported between instances of 'list' and 'tuple'
Python supports equality comparison between lists and tuples. However, it doesn’t support the rest of the comparison operators, as you can conclude from the final two examples. If you try to use them, then you get a TypeError telling you that the operation isn’t supported.
You can also compare lists and tuples of different lengths:
>>> [5, 6, 7] < [8]
True
>>> (5, 6, 7) < (8,)
True
>>> [5, 6, 7] == [5]
False
>>> (5, 6, 7) == (5,)
False
>>> [5, 6, 7] > [5]
True
>>> (5, 6, 7) > (5,)
True
In the first two examples, you get True as a result because 5 is less than 8. That fact is sufficient for Python to solve the comparison. In the second pair of examples, you get False. This result makes sense because the compared sequences don’t have the same length, so they can’t be equal.
In the final pair of examples, Python compares 5 with 5. They’re equal, so the comparison continues. Because there are no more values to compare in the right-hand operands, Python concludes that the left-hand operands are greater.
As you can see, comparing lists and tuples can be tricky. It’s also an expensive operation that, in the worst case, requires traversing two entire sequences. Things get more complex and expensive when the contained items are also sequences. In those situations, Python will also have to compare items in a value-by-value manner, which adds cost to the operation.
Remove ads
Boolean Operators and Expressions in Python
Python has three Boolean or logical operators: and, or, and not. They define a set of operations denoted by the generic operators AND, OR, and NOT. With these operators, you can create compound conditions.
In the following sections, you’ll learn how the Python Boolean operators work. Especially, you’ll learn that some of them behave differently when you use them with Boolean values or with regular objects as operands.
Boolean Expressions Involving Boolean Operands
You’ll find many objects and expressions that are of Boolean type or bool, as Python calls this type. In other words, many objects evaluate to True or False, which are the Python Boolean values.
For example, when you evaluate an expression using a comparison operator, the result of that expression is always of bool type:
>>> age = 20
>>> is_adult = age > 18
>>> is_adult
True
>>> type(is_adult)
<class 'bool'>
In this example, the expression age > 18 returns a Boolean value, which you store in the is_adult variable. Now is_adult is of bool type, as you can see after calling the built-in type() function.
You can also find Python built-in and custom functions that return a Boolean value. This type of function is known as a predicate function. The built-in all(), any(), callable(), and isinstance() functions are all good examples of this practice.
Consider the following examples:
>>> number = 42
>>> validation_conditions = (
... isinstance(number, int),
... number % 2 == 0,
... )
>>> all(validation_conditions)
True
>>> callable(number)
False
>>> callable(print)
True
In this code snippet, you first define a variable called number using your old friend the assignment operator. Then you create another variable called validation_conditions. This variable holds a tuple of expressions. The first expression uses isinstance() to check whether number is an integer value.
The second is a compound expression that combines the modulo (%) and equality (==) operators to create a condition that checks whether the input value is an even number. In this condition, the modulo operator returns the remainder of dividing number by 2, and the equality operator compares the result with 0, returning True or False as the comparison’s result.
Then you use the all() function to determine if all the conditions are true. In this example, because number = 42, the conditions are true, and all() returns True. You can play with the value of number if you’d like to experiment a bit.
In the final two examples, you use the callable() function. As its name suggests, this function allows you to determine whether an object is callable. Being callable means that you can call the object with a pair of parentheses and appropriate arguments, as you’d call any Python function.
The number variable isn’t callable, and the function returns False, accordingly. In contrast, the print() function is callable, so callable() returns True.
All the previous discussion is the basis for understanding how the Python logical operators work with Boolean operands.
Logical expressions involving and, or, and not are straightforward when the operands are Boolean. Here’s a summary. Note that x and y represent Boolean operands:
Operator Sample Expression Result
and x and y • True if both x and y are True
• False otherwise
or x or y • True if either x or y is True
• False otherwise
not not x • True if x is False
• False if x is True
This table summarizes the truth value of expressions that you can create using the logical operators with Boolean operands. There’s something to note in this summary. Unlike and and or, which are binary operators, the not operator is unary, meaning that it operates on one operand. This operand must always be on the right side.
Now it’s time to take a look at how the operators work in practice. Here are a few examples of using the and operator with Boolean operands:
>>> 5 < 7 and 3 == 3
True
>>> 5 < 7 and 3 != 3
False
>>> 5 > 7 and 3 == 3
False
>>> 5 > 7 and 3 != 3
False
In the first example, both operands return True. Therefore, the and expression returns True as a result. In the second example, the left-hand operand is True, but the right-hand operand is False. Because of this, the and operator returns False.
In the third example, the left-hand operand is False. In this case, the and operator immediately returns False and never evaluates the 3 == 3 condition. This behavior is called short-circuit evaluation. You’ll learn more about it in a moment.
Note: Short-circuit evaluation is also called McCarthy evaluation in honor of computer scientist John McCarthy.
In the final example, both conditions return False. Again, and returns False as a result. However, because of the short-circuit evaluation, the right-hand expression isn’t evaluated.
What about the or operator? Here are a few examples that demonstrate how it works:
>>> 5 < 7 or 3 == 3
True
>>> 5 < 7 or 3 != 3
True
>>> 5 > 7 or 3 == 3
True
>>> 5 > 7 or 3 != 3
False
In the first three examples, at least one of the conditions returns True. In all cases, the or operator returns True. Note that if the left-hand operand is True, then or applies short-circuit evaluation and doesn’t evaluate the right-hand operand. This makes sense. If the left-hand operand is True, then or already knows the final result. Why would it need to continue the evaluation if the result won’t change?
In the final example, both operands are False, and this is the only situation where or returns False. It’s important to note that if the left-hand operand is False, then or has to evaluate the right-hand operand to arrive at a final conclusion.
Finally, you have the not operator, which negates the current truth value of an object or expression:
>>> 5 < 7
True
>>> not 5 < 7
False
If you place not before an expression, then you get the inverse truth value. When the expression returns True, you get False. When the expression evaluates to False, you get True.
There is a fundamental behavior distinction between not and the other two Boolean operators. In a not expression, you always get a Boolean value as a result. That’s not always the rule that governs and and or expressions, as you’ll learn in the Boolean Expressions Involving Other Types of Operands section.
Remove ads
Evaluation of Regular Objects in a Boolean Context
In practice, most Python objects and expressions aren’t Boolean. In other words, most objects and expressions don’t have a True or False value but a different type of value. However, you can use any Python object in a Boolean context, such as a conditional statement or a while loop.
In Python, all objects have a specific truth value. So, you can use the logical operators with all types of operands.
Python has well-established rules to determine the truth value of an object when you use that object in a Boolean context or as an operand in an expression built with logical operators. Here’s what the documentation says about this topic:
By default, an object is considered true unless its class defines either a __bool__() method that returns False or a __len__() method that returns zero, when called with the object. Here are most of the built-in objects considered false:
constants defined to be false: None and False.
zero of any numeric type: 0, 0.0, 0j, Decimal(0), Fraction(0, 1)
empty sequences and collections: '', (), [], {}, set(), range(0)
(Source)
You can determine the truth value of an object by calling the built-in bool() function with that object as an argument. If bool() returns True, then the object is truthy. If bool() returns False, then it’s falsy.
For numeric values, you have that a zero value is falsy, while a non-zero value is truthy:
>>> bool(0), bool(0.0), bool(0.0+0j)
(False, False, False)
>>> bool(-3), bool(3.14159), bool(1.0+1j)
(True, True, True)
Python considers the zero value of all numeric types falsy. All the other values are truthy, regardless of how close to zero they are.
Note: Instead of a function, bool() is a class. However, because Python developers typically use this class as a function, you’ll find that most people refer to it as a function rather than as a class. Additionally, the documentation lists this class on the built-in functions page. This is one of those cases where practicality beats purity.
When it comes to evaluating strings, you have that an empty string is always falsy, while a non-empty string is truthy:
>>> bool("")
False
>>> bool(" ")
True
>>> bool("Hello")
True
Note that strings containing white spaces are also truthy in Python’s eyes. So, don’t confuse empty strings with whitespace strings.
Finally, built-in container data types, such as lists, tuples, sets, and dictionaries, are falsy when they’re empty. Otherwise, Python considers them truthy objects:
>>> bool([])
False
>>> bool([1, 2, 3])
True
>>> bool(())
False
>>> bool(("John", 25, "Python Dev"))
True
>>> bool(set())
False
>>> bool({"square", "circle", "triangle"})
True
>>> bool({})
False
>>> bool({"name": "John", "age": 25, "job": "Python Dev"})
True
To determine the truth value of container data types, Python relies on the .__len__() special method. This method provides support for the built-in len() function, which you can use to determine the number of items in a given container.
In general, if .__len__() returns 0, then Python considers the container a falsy object, which is consistent with the general rules you’ve just learned before.
All the discussion about the truth value of Python objects in this section is key to understanding how the logical operators behave when they take arbitrary objects as operands.
Boolean Expressions Involving Other Types of Operands
You can also use any objects, such as numbers or strings, as operands to and, or, and not. You can even use combinations of a Boolean object and a regular one. In these situations, the result depends on the truth value of the operands.
Note: Boolean expressions that combine two Boolean operands are a special case of a more general rule that allows you to use the logical operators with all kinds of operands. In every case, you’ll get one of the operands as a result.
You’ve already learned how Python determines the truth value of objects. So, you’re ready to dive into creating expressions with logic operators and regular objects.
To start off, below is a table that summarizes what you get when you use two objects, x and y, in an and expression:
If x is x and y returns
Truthy y
Falsy x
It’s important to emphasize a subtle detail in the above table. When you use and in an expression, you don’t always get True or False as a result. Instead, you get one of the operands. You only get True or False if the returned operand has either of these values.
Here are some code examples that use integer values. Remember that in Python, the zero value of numeric types is falsy. The rest of the values are truthy:
>>> 3 and 4
4
>>> 0 and 4
0
>>> 3 and 0
0
In the first expression, the left-hand operand (3) is truthy. So, you get the right-hand operand (4) as a result.
In the second example, the left-hand operand (0) is falsy, and you get it as a result. In this case, Python applies the short-circuit evaluation technique. It already knows that the whole expression is false because 0 is falsy, so Python returns 0 immediately without evaluating the right-hand operand.
In the final expression, the left-hand operand (3) is truthy. Therefore Python needs to evaluate the right-hand operand to make a conclusion. As a result, you get the right-hand operand, no matter what its truth value is.
Note: To dive deeper into the and operator, check out Using the “and” Boolean Operator in Python.
When it comes to using the or operator, you also get one of the operands as a result. This is what happens for two arbitrary objects, x and y:
If x is x or y returns
Truthy x
Falsy y
Again, the expression x or y doesn’t evaluate to either True or False. Instead, it returns one of its operands, x or y.
As you can conclude from the above table, if the left-hand operand is truthy, then you get it as a result. Otherwise, you get the second operand. Here are some examples that demonstrate this behavior:
>>> 3 or 4
3
>>> 0 or 4
4
>>> 3 or 0
3
In the first example, the left-hand operand is truthy, and or immediately returns it. In this case, Python doesn’t evaluate the second operand because it already knows the final result. In the second example, the left-hand operand is falsy, and Python has to evaluate the right-hand one to determine the result.
In the last example, the left-hand operand is truthy, and that fact defines the result of the expression. There’s no need to evaluate the right-hand operand.
An expression like x or y is truthy if either x or y is truthy, and falsy if both x and y are falsy. This type of expression returns the first truthy operand that it finds. If both operands are falsy, then the expression returns the right-hand operand. To see this latter behavior in action, consider the following example:
>>> 0 or []
[]
In this specific expression, both operands are falsy. So, the or operator returns the right-hand operand, and the whole expression is falsy as a result.
Note: To learn more about the or operator, check out Using the “or” Boolean Operator in Python.
Finally, you have the not operator. You can also use this one with any object as an operand. Here’s what happens:
If x is not x returns
Truthy False
Falsy True
The not operator has a uniform behavior. It always returns a Boolean value. This behavior differs from its sibling operators, and and or.
Here are some code examples:
>>> not 3
False
>>> not 0
True
In the first example, the operand, 3, is truthy from Python’s point of view. So, the operator returns False. In the second example, the operand is falsy, and not returns True.
Note: To better understand the not operator, check out Using the “not” Boolean Operator in Python.
In summary, the Python not operator negates the truth value of an object and always returns a Boolean value. This latter behavior differs from the behavior of its sibling operators and and or, which return operands rather than Boolean values.
Remove ads
Compound Logical Expressions and Short-Circuit Evaluation
So far, you’ve seen expressions with only a single or or and operator and two operands. However, you can also create compound logical expressions with multiple logical operators and operands.
To illustrate how to create a compound expression using or, consider the following toy example:
x1 or x2 or x3 or ... or xn
This expression returns the first truthy value. If all the preceding x variables are falsy, then the expression returns the last value, xn.
Note: In an expression like the one above, Python uses short-circuit evaluation. The operands are evaluated in order from left to right. As soon as one is found to be true, the entire expression is known to be true. At that point, Python stops evaluating operands. The value of the entire expression is that of the x that terminates the evaluation.
To help demonstrate short-circuit evaluation, suppose that you have an identity function, f(), that behaves as follows:
Takes a single argument
Displays the function and its argument on the screen
Returns the argument as its return value
Here’s the code to define this function and also a few examples of how it works:
>>> def f(arg):
... print(f"-> f({arg}) = {arg}")
... return arg
...
>>> f(0)
-> f(0) = 0
0
>>> f(False)
-> f(False) = False
False
>>> f(1.5)
-> f(1.5) = 1.5
1.5
The f() function displays its argument, which visually confirms whether you called the function. It also returns the argument as you passed it in the call. Because of this behavior, you can make the expression f(arg) be truthy or falsy by specifying a value for arg that’s truthy or falsy, respectively.
Now, consider the following compound logical expression:
>>> f(0) or f(False) or f(1) or f(2) or f(3)
-> f(0) = 0
-> f(False) = False
-> f(1) = 1
1
In this example, Python first evaluates f(0), which returns 0. This value is falsy. The expression isn’t true yet, so the evaluation continues from left to right. The next operand, f(False), returns False. That value is also falsy, so the evaluation continues.
Next up is f(1). That evaluates to 1, which is truthy. At that point, Python stops the evaluation because it already knows that the entire expression is truthy. Consequently, Python returns 1 as the value of the expression and never evaluates the remaining operands, f(2) and f(3). You can confirm from the output that the f(2) and f(3) calls don’t occur.
A similar behavior appears in an expression with multiple and operators like the following one:
x1 and x2 and x3 and ... and xn
This expression is truthy if all the operands are truthy. If at least one operand is falsy, then the expression is also falsy.
In this example, short-circuit evaluation dictates that Python stops evaluating as soon as an operand happens to be falsy. At that point, the entire expression is known to be false. Once that’s the case, Python stops evaluating operands and returns the falsy operand that terminated the evaluation.
Here are two examples that confirm the short-circuiting behavior:
>>> f(1) and f(False) and f(2) and f(3)
-> f(1) = 1
-> f(False) = False
False
>>> f(1) and f(0.0) and f(2) and f(3)
-> f(1) = 1
-> f(0.0) = 0.0
0.0
In both examples, the evaluation stops at the first falsy term—f(False) in the first case, f(0.0) in the second case—and neither the f(2) nor the f(3) call occurs. In the end, the expressions return False and 0.0, respectively.
If all the operands are truthy, then Python evaluates them all and returns the last (rightmost) one as the value of the expression:
>>> f(1) and f(2.2) and f("Hello")
-> f(1) = 1
-> f(2.2) = 2.2
-> f(Hello) = Hello
'Hello'
>>> f(1) and f(2.2) and f(0)
-> f(1) = 1
-> f(2.2) = 2.2
-> f(0) = 0
0
In the first example, all the operands are truthy. The expression is also truthy and returns the last operand. In the second example, all the operands are truthy except for the last one. The expression is falsy and returns the last operand.
Remove ads
Idioms That Exploit Short-Circuit Evaluation
As you dig into Python, you’ll find that there are some common idiomatic patterns that exploit short-circuit evaluation for conciseness of expression, performance, and safety. For example, you can take advantage of this type of evaluation for:
Avoiding an exception
Providing a default value
Skipping a costly operation
To illustrate the first point, suppose you have two variables, a and b, and you want to know whether the division of b by a results in a number greater than 0. In this case, you can run the following expression or condition:
>>> a = 3
>>> b = 1
>>> (b / a) > 0
True
This code works. However, you need to account for the possibility that a might be 0, in which case you’ll get an exception:
>>> a = 0
>>> b = 1
>>> (b / a) > 0
Traceback (most recent call last):
...
ZeroDivisionError: division by zero
In this example, the divisor is 0, which makes Python raise a ZeroDivisionError exception. This exception breaks your code. You can skip this error with an expression like the following:
>>> a = 0
>>> b = 1
>>> a != 0 and (b / a) > 0
False
When a is 0, a != 0 is false. Python’s short-circuit evaluation ensures that the evaluation stops at that point, which means that (b / a) never runs, and the error never occurs.
Using this technique, you can implement a function to determine whether an integer is divisible by another integer:
def is_divisible(a, b):
return b != 0 and a % b == 0
In this function, if b is 0, then a / b isn’t defined. So, the numbers aren’t divisible. If b is different from 0, then the result will depend on the remainder of the division.
Selecting a default value when a specified value is falsy is another idiom that takes advantage of the short-circuit evaluation feature of Python’s logical operators.
For example, say that you have a variable that’s supposed to contain a country’s name. At some point, this variable can end up holding an empty string. If that’s the case, then you’d like the variable to hold a default county name. You can also do this with the or operator:
>>> country = "Canada"
>>> default_country = "United States"
>>> country or default_country
'Canada'
>>> country = ""
>>> country or default_country
'United States'
If country is non-empty, then it’s truthy. In this scenario, the expression will return the first truthy value, which is country in the first or expression. The evaluation stops, and you get "Canada" as a result.
On the other hand, if country is an empty string, then it’s falsy. The evaluation continues to the next operand, default_country, which is truthy. Finally, you get the default country as a result.
Another interesting use case for short-circuit evaluation is to avoid costly operations while creating compound logical expressions. For example, if you have a costly operation that should only run if a given condition is false, then you can use or like in the following snippet:
data_is_clean or clean_data(data)
In this construct, your clean_data() function represents a costly operation. Because of short-circuit evaluation, this function will only run when data_is_clean is false, which means that your data isn’t clean.
Another variation of this technique is when you want to run a costly operation if a given condition is true. In this case, you can use the and operator:
data_is_updated and process_data(data)
In this example, the and operator evaluates data_is_updated. If this variable is true, then the evaluation continues, and the process_data() function runs. Otherwise, the evaluation stops, and process_data() never runs.
Remove ads
Compound vs Chained Expressions
Sometimes you have a compound expression that uses the and operator to join comparison expressions. For example, say that you want to determine if a number is in a given interval. You can solve this problem with a compound expression like the following:
>>> number = 5
>>> number >= 0 and number <= 10
True
>>> number = 42
>>> number >= 0 and number <= 10
False
In this example, you use the and operator to join two comparison expressions that allow you to find out if number is in the interval from 0 to 10, both included.
In Python, you can make this compound expression more concise by chaining the comparison operators together. For example, the following chained expression is equivalent to the previous compound one:
>>> number = 5
>>> 0 <= number <= 10
True
This expression is more concise and readable than the original expression. You can quickly realize that this code is checking if the number is between 0 and 10. Note that in most programming languages, this chained expression doesn’t make sense. In Python, it works like a charm.
In other programming languages, this expression would probably start by evaluating 0 <= number, which is true. This true value would then be compared with 10, which doesn’t make much sense, so the expression fails.
Python internally processes this type of expression as an equivalent and expression, such as 0 <= number and number <= 10. That’s why you get the correct result in the example above.
Conditional Expressions or the Ternary Operator
Python has what it calls conditional expressions. These kinds of expressions are inspired by the ternary operator that looks like a ? b : c and is used in other programming languages. This construct evaluates to b if the value of a is true, and otherwise evaluates to c. Because of this, sometimes the equivalent Python syntax is also known as the ternary operator.
However, in Python, the expression looks more readable:
variable = expression_1 if condition else expression_2
This expression returns expression_1 if the condition is true and expression_2 otherwise. Note that this expression is equivalent to a regular conditional like the following:
if condition:
variable = expression_1
else:
variable = expression_2
So, why does Python need this syntax? PEP 308 introduced conditional expressions as an effort to avoid the prevalence of error-prone attempts to achieve the same effect of a traditional ternary operator using the and and or operators in an expression like the following:
variable = condition and expression_1 or expression_2
However, this expression doesn’t work as expected, returning expression_2 when expression_1 is falsy.
Some Python developers would avoid the syntax of conditional expressions in favor of a regular conditional statement. In any case, this syntax can be handy in some situations because it provides a concise tool for writing two-way conditionals.
Here’s an example of how to use the conditional expression syntax in your code:
>>> day = "Sunday"
>>> open_time = "11AM" if day == "Sunday" else "9AM"
>>> open_time
'11AM'
>>> day = "Monday"
>>> open_time = "11AM" if day == "Sunday" else "9AM"
>>> open_time
'9AM'
When day is equal to "Sunday", the condition is true and you get the first expression, "11AM", as a result. If the condition is false, then you get the second expression, "9AM". Note that similarly to the and and or operators, the conditional expression returns the value of one of its expressions rather than a Boolean value.
Remove ads
Identity Operators and Expressions in Python
Python provides two operators, is and is not, that allow you to determine whether two operands have the same identity. In other words, they let you check if the operands refer to the same object. Note that identity isn’t the same thing as equality. The latter aims to check whether two operands contain the same data.
Note: To learn more about the difference between identity and equality, check out Python ‘!=’ Is Not ‘is not’: Comparing Objects in Python.
Here’s a summary of Python’s identity operators. Note that x and y are variables that point to objects:
Operator Sample Expression Result
is x is y • True if x and y hold a reference to the same in-memory object
• False otherwise
is not x is not y • True if x points to an object different from the object that y points to
• False otherwise
These two Python operators are keywords instead of odd symbols. This is part of Python’s goal of favoring readability in its syntax.
Here’s an example of two variables, x and y, that refer to objects that are equal but not identical:
>>> x = 1001
>>> y = 1001
>>> x == y
True
>>> x is y
False
In this example, x and y refer to objects whose value is 1001. So, they’re equal. However, they don’t reference the same object. That’s why the is operator returns False. You can check an object’s identity using the built-in id() function:
>>> id(x)
4417772080
>>> id(y)
4417766416
As you can conclude from the id() output, x and y don’t have the same identity. So, they’re different objects, and because of that, the expression x is y returns False. In other words, you get False because you have two different instances of 1001 stored in your computer’s memory.
When you make an assignment like y = x, Python creates a second reference to the same object. Again, you can confirm that with the id() function or the is operator:
>>> a = "Hello, Pythonista!"
>>> b = a
>>> id(a)
4417651936
>>> id(b)
4417651936
>>> a is b
True
In this example, a and b hold references to the same object, the string "Hello, Pythonista!". Therefore, the id() function returns the same identity when you call it with a and b. Similarly, the is operator returns True.
Note: You should note that, on your computer, you’ll get a different identity number when you call id() in the example above. The key detail is that the identity number will be the same for a and b.
Finally, the is not operator is the opposite of is. So, you can use is not to determine if two names don’t refer to the same object:
>>> x = 1001
>>> y = 1001
>>> x is not y
True
>>> a = "Hello, Pythonista!"
>>> b = a
>>> a is not b
False
In the first example, because x and y point to different objects in your computer’s memory, the is not operator returns True. In the second example, because a and b are references to the same object, the is not operator returns False.
Note: The syntax not x is y also works the same as x is not y. However, the former syntax looks odd and is difficult to read. That’s why Python recognizes is not as an operator and encourages its use for readability.
Again, the is not operator highlights Python’s readability goals. In general, both identity operators allow you to write checks that read as plain English.
Remove ads
Membership Operators and Expressions in Python
Sometimes you need to determine whether a value is present in a container data type, such as a list, tuple, or set. In other words, you may need to check if a given value is or is not a member of a collection of values. Python calls this kind of check a membership test.
Note: For a deep dive into how Python’s membership tests work, check out Python’s “in” and “not in” Operators: Check for Membership.
Membership tests are quite common and useful in programming. As with many other common operations, Python has dedicated operators for membership tests. The table below lists the membership operators in Python:
Operator Sample Expression Result
in value in collection • True if value is present in collection
• False otherwise
not in value not in collection • True if value is not present in collection of values
• False otherwise
As usual, Python favors readability by using English words as operators instead of potentially confusing symbols or combinations of symbols.
Note: The syntax not value in collection also works in Python. However, this syntax looks odd and is difficult to read. So, to keep your code clean and readable, you should use value not in collection, which almost reads as plain English.
The Python in and not in operators are binary. This means that you can create membership expressions by connecting two operands with either operator. However, the operands in a membership expression have particular characteristics:
Left operand: The value that you want to look for in a collection of values