Operators
Python offers a plethora of operators, grouped into categories:
- Arithmetic
- Assignment
- Comparison
- Logical
- Identity
- Membership
- Bitwise
Each one of these categories serve a different purpose. In this section, we will be exploring the first four categories, then whenever each one is needed, we will include it in its own section.
Arithmetic Operators
Creating variables just to hold values is quiet boring, we need some way to manipulate them. This is where operators shine, they let us perform well.. operations. Arithmetic operators deal mostly with numeric values. The four basic operators are:
+which adds two numbers-which subtracts the first number from the second*computes the product of two values/division which divides the first number by the second
x = 1 + 2y = 3 * 4z = y / x - 1print(x, y, z)Note
The division operator always yields a float. Dividing by zero is not allowed and will raise a
ZeroDivisionError.
We are left with:
**which raises the first number to the power of the second%which returns the remainder after division of the first number by the second//which performs floor division, i.e. it goes down to the nearest integer
The ** operator raises the first number to the power of the second.
print(2 ** 3) #8print(3 ** 2) #9print(10 ** 0) #1print(10 ** -1) #0.1Next in line is the // floor division. We can think of it as an elevator down-stairs. This behaves like the division, but if the result has a decimal part (wasn’t divisible), it goes down to the nearest integer.
print(5 // 2) #2print(4 // 2) #2print(8 // 3) #2print(4 // 5) #0print(1.2 // 1) #1print(-0.5 // 1) #-1print(-1.5 // 1) #-2The yielded type may not always be an integer. This is something that few people know about, if any of the numbers is a float, the result would be a float (integer with a .0 at the end of it).
print(4 // 2) #2print(4.0 // 2) #2.0print(4 // 2.0) #2.0print(4.0 // 2.0) #2.0We also have the modulo operator %, which takes two numbers a and b and returns the remainder after division of a by b.
print(5 % 2) #1print(14 % 4) #2print(28 % -5) #-2The modulo operator always yields a negative value, if the second number is negative.
print(5 % 3) #2print(-5 % 3) #1print(5 % -3) #-1print(-5 % -3) #-2There is a relation between the floor division and the modulo operator, which is:
so
Common Type Conversion
When we say that an arithmetic operation uses the phrase: “The numeric arguments are converted into a common type”, this means that the built-in operators work as follows:
- If either arguments is a complex, the other is converted to complex.
- If either is a floating number, the other is converted to a floating number.
- If either is a integer, the other is converted to a integer.
- Otherwise, both must be integers and conversion is not necessary.
Addition, subtraction, multiplication, division, floor division, modulo and power obey the previous rule. While the floor division yields an integer, the value is converted to the common type.
Assignment Operators
An assignment operator = is used to bind (or rebind) a value to a variable. This is done by evaluating the right-hand side of the assignment operator and then binding the value to the left-hand side.
x = 10y = 20z = 30print(x) #10print(y) #20print(z) #30x = 40 #rebindprint(x) #40We can also use the assignment operator to bind multiple variables to a single value.
x = y = z = 10print(x) #10print(y) #10print(z) #10Augmented Assignment Operators
Augmented assignment operators are a shorthand for the assignment operator. They are used to perform an operation and then assign the result to the left-hand side.
x = 10x += 10print(x) #20x += 10 is equivalent to x = x + 10. In general x op= y is equivalent to x = x op y, where op is the operator.
Following is a list of augmented assignment operators: +=, -=, *=, @=, /=, //=, %=, **=, >>=, <<=, &=, ^=, |=
x = 10x -= 2 #x = x - 2print(x) #8x *= 10 #x = x * 10print(x) #80x /= 3 #x = x / 3print(x) #26.666666666666668x //= 2 #x = x // 2print(x) #13.0x %= 10 #x = x % 10print(x) #3.0Comparison Operators
Python supports the usually comparison operators:
==Equal!=Not equal>Greater than<Less than>=Greater than or equal<=Less than or equal
All of these operations have the same precedence level. Comparison operators always return a boolean value True or False.
x = 10y = 20z = 30print(x == y) #Falseprint(x != y) #Trueprint(x > y) #Falseprint(x >= y) #Falseprint(x <= y) #Trueprint(x < z) #Trueprint(x > z) #Falseprint(x >= z) #Falseprint(x <= z) #TrueThe equality comparison (== and !=) checks if two values have the same identity.
Note
One can get the identity of an object using the
idfunction.
By default, an order comparison (<, >, <=, and >=) is not provided on all types, so writing something like None < 2 will raise a TypeError.
If we were using a mix of booleans, integers, or floats, then they are converted to a common type, and then the comparison is performed. If we have two strings, then the comparison is performed lexicographically.
Info
Lexicographical comparison is the comparison of strings based on the dictionary order of the characters. It is performed by comparing the Unicode code points of the characters in the strings.
Comparison Chaining
Comaprison operators can be chained together similar to mathematical expressions. is equivalent to and , except that y is evaluated only once (but in both cases z is not evaluated at all when x < y is found to be false).
Comparison chaining isn’t limited to operators of the same nature (i.e. only greater thans, or only less thans), it can be used with any combination of operators.
x = 10y = 20z = 30print(x < z > y) #Trueprint(x < y != z) #Trueprint(x == y == z) #Falseprint(x != y < z) #TrueSaying y is evaluated once is important, suppose that y is a function call, and it has a side effect, such as printing a value to the console. If y is evaluated twice, the side effect will be executed twice. In an expression which contains comparison chaining, the evaluation stops once we reach a False value.
print(1 != print("Hello") != 2) #True, prints Hello onceprint(1 != print("Hello") && print("Hello") != 2) #True, prints Hello twiceprint(1 == 2 == print("Hello")) #False, since we have short-circuiting, print("Hello") is not evaluatedLogical Operators
Python supports the following logical operators:
notandor
The operator not yields True if its argument is False, False otherwise.
The expression x and y first evaluates x; if x is False, its value is returned; otherwise, y is evaluated and the resulting value is returned.
The expression x or y first evaluates x; if x is True, its value is returned; otherwise, y is evaluated and the resulting value is returned.
Truth Table
| x | y | x and y | x or y | not x |
|---|---|---|---|---|
| False | False | False | False | True |
| False | True | False | True | True |
| True | False | False | True | False |
| True | True | True | True | False |
print(not True) #Falseprint(not False) #Trueprint(True and False) #Falseprint(True and True) #Trueprint(True or False) #Trueprint(False or False) #FalseThese operators are not restricted to only booleans, they can take any value and depending on the truthiness of the value, the operator will return the value. The returned value is not necessarily a boolean, but rather return the last evaluated argument. This is sometimes useful if for instance you want to set a default value for a variable if it is not set.
print(True and 1) #1print(False and 1) #Falseprint(True or 1) #Trueprint(False or 1) #1print(not 1) #Falseprint(not 0) #Truename = ""print(name or "Guest") #Guestname = "Ali"print(name or "Guest") #AliIn the first case, the expression name or "Guest" yields the desired value, since name is an empty string, it will evaluate the second argument and return it. In the second case, the expression name or "Guest" will evaluate the first argument and return it, since name is not an empty string.
An important thing to keep in mind is that both operators and and or have short-circuiting behavior. This means that the second argument is not evaluated if the first argument is enough to determine the result.
- For the
and, if the first argument isFalse, the second argument is not evaluated and the result isFalse. - For the
or, if the first argument isTrue, the second argument is not evaluated and the result is the first argument.
print(0 and True) #0 (since 0 is Falsy)print(3 or False) #3 (since 3 is Truthy)Precedence and Associativity
Operators have a precedence and associativity. The precedence is the order in which the operators are evaluated. The associativity is the order in which the operators are grouped.
The following table shows the precedence of the operators in Python.
| Operator | Description | Associativity |
|---|---|---|
(expressions) [expressions] {key: value} {expressions} | Parentheses, lists, dictionaries, sets | Left to right |
x[index] x[index:index] x(arguments) | Indexing, slicing, function calls | Left to right |
await x | Await expression | Left to right |
** | Power | Right to left |
+x -x ~x | Unary plus, unary minus, bitwise NOT | Right to left |
*, @, /, //, % | Multiplication, multiplication by matrix, division, floor division, modulo | Left to right |
+, - | Addition, subtraction | Left to right |
<< >> | Bitwise left shift, bitwise right shift | Left to right |
& | Bitwise AND | Left to right |
^ | Bitwise XOR | Left to right |
| | Bitwise OR | Left to right |
in not in is is not < > <= >= != == | Membership, identity, comparison | Left to right |
not | Logical NOT | Right to left |
and | Logical AND | Left to right |
or | Logical OR | Left to right |
if-else | Conditional expression | Right to left |
lambda | Lambda expression | |
:= | Assignment expression | Right to left |
The first row in the table is the highest precedence, the last row is the lowest precedence. As we can see there are some columns with multiple operators, these operators have the same precedence. But in an expression with multiple operators having the same precedence, the associativity is used to determine the order of evaluation.
Note
We have added all the operators here, even the ones that we didn’t mention in this section, nor the previous ones. This is to give you a complete picture of the operators in Python.
Exercises
Exercise 1: Assignment Operator
Write a program which creates three variables x, y and z, and assigns them the values 10, 20 and 30 respectively. Then print the values of x, y and z.
x = 10y = 20z = 30print(x, y, z)Exercise 2: Find the output
What is the output of the following code?
x = 10y = 3print(x + y * 2)The output of the code is 16.
Exercise 3: Find the output
What is the output of the following code?
a = 7a += 3a *= 2print(a)The output of the code is 20.
Exercise 4: Find the output
What is the output of the following code?
print(True and False or True)print(True and (False or True))The output of the code is True and True.
Exercise 5: Logical Operators
Explain why True or anything always returns True, but False and anything always returns False.
Because the or operator returns True if either of the arguments is True, and the and operator returns False if either of the arguments is False.
