3. Operators

3.1. Basic arithmetic operators

When dealing with integers and floats, you can apply the following basic math operators.

1a = 1 + 1 # addition, 2
2b = 1 - 1 # subtraction, 0
3c = 1 * 2 # multiplication, 2
4d = 2 / 4 # division, 2
5e = 4 // 3 # floor division, 1 (quotient)
6f = 4 % 3 # modulus, 1 (remainder)
7g = 4 ** 2 # exponentiation, 16

Pay attention to the multiplication and division operators, as they are * (asterisk) and / (forward slash), correspondingly. Also, there are 3 ways to divide using /, // and %.

  • / gives you a real number (decimal)

  • // gives you the quotient

  • % gives you the remainder

3.1.1. Exercise

For the following 2 variables,

  • print what is a + b?

  • print what is a - b?

  • print what is a x b?

  • print what is a ÷ b?

1a = 17
2b = 5

Solution.

1print(f'{a} + {b} = {a + b}')
2print(f'{a} - {b} = {a - b}')
3print(f'{a} * {b} = {a * b}')
4print(f'{a} / {b} = {a / b}')

3.1.2. Exercise

Can you express 4 divided by 3 in terms of an improper fraction?

Solution.

1dividen = 4
2divisor = 3
3quotient = dividen // divisor
4remainder = dividen % divisor
5
6s = f'{dividen} / {divisor} = {quotient} and {remainder}/{divisor}'
7print(s)

3.2. Compound assignment operators

If you had an integer variable, and wanted to add a number to it and reassign the result back to itself, how would you do so? Here’s a way.

1a = 15
2a = a + 2 # add 2 to a, and assign the result back to a

A shorter way of expressing this operation is through using a compound assignment operator.

1a = 15
2a += 2

Here are other types of compound assignment operators.

 1# compound add
 2a = 10
 3a += 4
 4
 5# compound subtract
 6b = 10
 7b -= 4
 8
 9# compound multiply
10c = 10
11c *= 2
12
13# compound divide
14d = 10
15d /= 2

3.2.1. Exercise

Let’s say you have someone’s age.

  • What is the person’s age in 10 years?

  • What’s the person’s age 2 years ago from the previous result?

  • What’s double the person’s age from the previous result?

  • What’s half the person’s age from the previous result?

1age = 15

Solution.

 1age += 10
 2print(f'age: {age}')
 3
 4age -= 2
 5print(f'age: {age}')
 6
 7age *= 2
 8print(f'age: {age}')
 9
10age /= 2
11print(f'age: {age}')

3.3. Bitwise operators

All data is represented as a list of bits. A bit is just a space in the computer’s memory that can store the value 0 or 1. As a first step to understanding bits, it makes a lot of sense to understand representations of integers through bits. In Python, integers are represented with 32 bits. Since 1 byte is equal to 8 bits, an integer is said to use 4 bytes (or 32 bits). When we declare and initialize an integer variable, Python finds contiguous spaces in memory (32 bits or 4 bytes) to store the representation of the value. For example, the number 8 is represented as: 0000000000001000. The number 8 is said to be in decimal form and the number 0000000000001000 is said to be in binary form; they are equivalent, but using different representation schemes. Bitwise operators work to manipulate these bits.

If 8 in decimal is represented as 0000000000001000, then the bitwise not ~, when applied to the decimal number, changes the bits to be 1111111111110111, and the resulting decimal is -9. Note that ~ flips all 0 bits to 1 and all 1 bits to 0. Here’s a cheat sheet on the bitwise operators.

  • ~ reverses the bit (0 is turned to 1, 1 is turned to 0)

  • | if either bit is 1, then 1, else 0

  • & if both bits are 1, then 1, else 0

  • ^ if one or the other bit is 1, then 1, else 0

  • << shifts the bits to the left (padding zeros to the right)

  • >> shifts the bits to the right (padding zeros to the left)

 1a = 42
 2b = 15
 3
 4# bitwise not
 5q = ~42
 6
 7# btiwse or
 8r = a | b
 9
10# bitwise and
11s = a & b
12
13# bitwise XOR
14t = a ^ b
15
16# bitwise left shift
17a = 1
18
19x = a << 1
20y = a << 2
21z = a << 3
22
23# bitwise right shift
24a = 8
25
26x = a >> 1
27y = a >> 2
28z = a >> 3

3.3.1. Exercise

What is the result of 16

  • shifted by 1 bit to the left?

  • shifted by 2 bits to the left?

  • shifted by 3 bits to the left?

  • shifted by 1 bit to the right?

  • shifted by 2 bits to the right?

  • shifted by 3 bits to the right?

Solution.

1print(16 << 1) # 32
2print(16 << 2) # 64
3print(16 << 3) # 128
4print(16 >> 1) # 8
5print(16 >> 1) # 4
6print(16 >> 1) # 2

3.4. Relational operators

Relational operators are also called comparison operators. These operators compare two things and the evaluation of the comparison must always be True or False.

 1num1 = 4
 2num2 = 2
 3
 4# equality
 5a = num1 == num2
 6
 7# non-equality
 8b = num1 != num2
 9
10# greater than
11c = num1 > num2
12
13# less than
14d = num1 < num2
15
16# greater than or equal
17e = num1 >= num2
18
19# less than or equal
20f = num1 <= num2

3.4.1. Exercise

You have the ages of Jack, John, Mary and Jane.

  • Is Jack older than John?

  • Is Jack younger than Mary?

  • Is Jack’s age equal to Jane?

1jack = 28
2john = 35
3mary = 24
4jane = 28

Solution.

1# is jack older than john?
2print(jack > john)
3
4# is jack younger than mary?
5print(jack < mary)
6
7# is jack equal to jane?
8print(jack == mary)

3.5. Boolean logical operators

You can chain boolean values or comparisons to evaluate to True or False using boolean logical operators. The following are examples of such operators.

 1a = False
 2b = False
 3
 4# boolean or
 5a_or_b = a | b
 6
 7# boolean and
 8a_and_b = a & b
 9
10# boolean XOR
11a_xor_b = a ^ b
12
13# not
14not_a = not a
15
16# short-circuit or
17a_short_or_b = a or b
18
19# short-circuit and
20a_short_and_b = a and b
21
22# ternary
23ternary = True if a else False

Note

When you have a boolean expression with all boolean and, this expression is called a conjunction. When you have a boolean expression with all boolean or, this expression is called a disjunction. In a conjunction, all sub-expressions or evaluations must be true for the overall evaluation to be true. In a disjunction, only 1 sub-expression must be true for the overall evaluation to be true.

Here’s some examples of conjunctions True and True and True and True and True and False and True. The first conjunction evaluates to true since all sub-expressions are true. The second conjunction evaluates to false since one of the sub-expression is false.

Here’s some examples of disjunctions True or False or True or False and False or False. The first disjunction evaluates to true since at least one of the sub-expression is true. The second disjunction evaluates to false since none of the sub-expressions are true.

Note

Another way to mimic the ternary operator is to use tuples with indexing. For example, if we have the tuple ('boy', 'girl'), we can get boy if we do ('boy', 'girl')[0] or girl if we do ('boy', 'girl')[1]. We can also use booleans, since True is 1 and False is 0

  • ('boy', 'girl')[False] results in boy

  • ('boy', 'girl')[True] results in girl

# True is saying 1, 'girl'
# False is saying 0, 'boy'
print(('boy', 'girl')[True])
print(('boy', 'girl')[False])

# or if we had gender as a boolean
gender = True
print(('boy', 'girl')[gender])

3.5.1. Exercise

You have the ages of Jack, John, Mary and Jane.

  • Is Jack older than John or Mary?

  • Is Jack younger than Mary and Jane?

  • Is Jack’s age equal to Jane and less than John?

1jack = 28
2john = 35
3mary = 24
4jane = 28

Solution.

1# is jack older than john or mary?
2print(jack > john or jack > mary)
3
4# is jack younger than mary and jane?
5print(jack < mary and jack < jane)
6
7# is jack equal to jane and less than john?
8print(jack == mary and jack < john)

3.6. Parentheses

Parentheses can be used in math operations to give priority to which operations to do first. Look at the examples below. There is a difference between 4 + 2 * 2 versus (4 + 2) * 2.

1# results in 8
2result = 4 + 2 * 2
3
4# results in 12
5result = (4 + 2) * 2

3.7. List unpacking

We have talked about unpacking tuples, but lists may also be unpacked.

1numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
2
3# x is 1
4# y is [2, 3, 4, 5, 6, 7, 8, 9]
5# z is 10
6x, *y, z = numbers

Just as in unpacking values from tuples, when we unpack values from a list, we can use _ to ignore values or ranges of values.

1numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
2
3# first and last values are ignored using underscore _
4# y is [2, 3, 4, 5, 6, 7, 8, 9]
5_, *y, _ = numbers

We can also use list unpacking to merge two lists as follows.

1boys = ['John', 'Jack', 'Jeremy']
2girls = ['Mary', 'Nancy', 'Joyce']
3
4names = [*boys, *girls]

Note that you do not have to unpack lists to merge their elements into one list. You can simply use the + operator to merge the elements of two lists as follows.

1boys = ['John', 'Jack', 'Jeremy']
2girls = ['Mary', 'Nancy', 'Joyce']
3names = boys + girls

3.8. Merging dictionaries via unpacking

If you want to merge the key-value pairs of 2 maps/dictionaries, use the ** operator as follows.

1name = {'first_name': 'John', 'last_name': 'Doe'}
2address = {
3    'address': '123 Main Street',
4    'city': 'Washington',
5    'state': 'DC',
6    'zip': 20050
7}
8
9person = {**name, **address}

3.8.1. Exercise

There are four major competitions, called slams, in tennis: Australian Open, French Open, Wimbledon and US Open. The results (data) below are how many times Roger Federer has won each one. Combine these individual results at the slams into one map (dictionary).

1australian_slam = {'australian': 6}
2french_slam = {'french': 1}
3wimbledon_slam = {'wimbledon': 8},
4us_slam = {'us': 5}

Solution.

1slams = {**australian_slam, **french_slam, **wimbledon_slam, **us_slam}
2print(slams)