# Module 1: Optional Python review¶

Are you still new to Python? Or your python skill is a bit rusty?

Then, feel free to use this to learn or refresh Python basics! You don't have to submit this notebook. It is just for your own reference.

## 1. Built-in object types¶

### 1.1 Int and Float¶

In [ ]:

Copied!

```
# Declaring an integer and a float variable
x = 10
y = 3.0
k = x + y + 100
# Comments start with the hash symbol
# y = 10
# The value stored in the variable can be inspected by using print statement.
# Type of a variable var can be checked by calling type(var)
print("The value of x is", x, "and it is of type", type(x))
# f-strings can be used to write more elegant print statement.
print(f"The value of y is {y} and it is of type {type(y)}")
print(f"The value of k is {k} and it is of type {type(k)}")
# casting int to float
print(f"x is of type {type(x)}")
x = float(x)
print(f"x is of type {type(x)} after casting")
```

# Declaring an integer and a float variable
x = 10
y = 3.0
k = x + y + 100
# Comments start with the hash symbol
# y = 10
# The value stored in the variable can be inspected by using print statement.
# Type of a variable var can be checked by calling type(var)
print("The value of x is", x, "and it is of type", type(x))
# f-strings can be used to write more elegant print statement.
print(f"The value of y is {y} and it is of type {type(y)}")
print(f"The value of k is {k} and it is of type {type(k)}")
# casting int to float
print(f"x is of type {type(x)}")
x = float(x)
print(f"x is of type {type(x)} after casting")

In [ ]:

Copied!

```
# Arithmetic operators
# Addition
z = x + y
print(f"Adding x and y gives {z}")
# Subtraction
z = x - y
print(f"Subtracting y from x gives {z}")
# Multiplication
z = x * y
print(f"Multiplying x and y gives {z}")
# Division
z = x / y
print(f"x divided by y gives {z}")
# Floor Division
z = x // y
print(f"x divided by y gives {z} as quotient")
# Modulus Operator
z = x % y
print(f"x divided by y gives {z} as reminder")
# Exponentiation
z = x ** y
print(f"x raised to y gives {z}")
# self increment by 1
x = x + 1
# This is equivalent to x += 1
print(f"x + 1 gives {x}")
```

# Arithmetic operators
# Addition
z = x + y
print(f"Adding x and y gives {z}")
# Subtraction
z = x - y
print(f"Subtracting y from x gives {z}")
# Multiplication
z = x * y
print(f"Multiplying x and y gives {z}")
# Division
z = x / y
print(f"x divided by y gives {z}")
# Floor Division
z = x // y
print(f"x divided by y gives {z} as quotient")
# Modulus Operator
z = x % y
print(f"x divided by y gives {z} as reminder")
# Exponentiation
z = x ** y
print(f"x raised to y gives {z}")
# self increment by 1
x = x + 1
# This is equivalent to x += 1
print(f"x + 1 gives {x}")

### 1.2 Booleans and None¶

In [ ]:

Copied!

```
# True and False are the key words that represent bool values in python
a = True
b = False
print(f"a is {a} and b is {b}")
print(f"Type of variable a and b is {type(a)}")
# None in python represents the absence of something; similar to null value
c = None
print(f"c is {c} and is of type {type(c)}")
# Any non-zero integer value is true and zero is false.
# Also anything with a non-zero length is true and empty sequences are false.
```

# True and False are the key words that represent bool values in python
a = True
b = False
print(f"a is {a} and b is {b}")
print(f"Type of variable a and b is {type(a)}")
# None in python represents the absence of something; similar to null value
c = None
print(f"c is {c} and is of type {type(c)}")
# Any non-zero integer value is true and zero is false.
# Also anything with a non-zero length is true and empty sequences are false.

In [ ]:

Copied!

```
# logical operators
# and, or and not operate on bool variables
# OR operator: Gives True when either of the expressions evaluates to True
# expr1 or expr2
print(f"a or b is {a or b}")
print(f"a or a is {a or a}")
print(f"b or b is {b or b}")
# AND operator: Gives True when both the expressions evaluates to True
# expr1 and expr2
print(f"a and b is {a and b}")
print(f"a and a is {a and a}")
print(f"b and b is {b and b}")
# NOT operator: negates a bool
# not expr1
print(f"Not of a is {not a}")
```

# logical operators
# and, or and not operate on bool variables
# OR operator: Gives True when either of the expressions evaluates to True
# expr1 or expr2
print(f"a or b is {a or b}")
print(f"a or a is {a or a}")
print(f"b or b is {b or b}")
# AND operator: Gives True when both the expressions evaluates to True
# expr1 and expr2
print(f"a and b is {a and b}")
print(f"a and a is {a and a}")
print(f"b and b is {b and b}")
# NOT operator: negates a bool
# not expr1
print(f"Not of a is {not a}")

In [ ]:

Copied!

```
# comparison operators
x = 10
y = 3.0
z = 5
# greater that, less than, greater than equal to and lesser than equal to
x > y
x >= y
x < y
x <= y
# equals and not equals
x == y
x != y
# Chained Expressions
x > y > z
(x > y) or (x > z)
```

# comparison operators
x = 10
y = 3.0
z = 5
# greater that, less than, greater than equal to and lesser than equal to
x > y
x >= y
x < y
x <= y
# equals and not equals
x == y
x != y
# Chained Expressions
x > y > z
(x > y) or (x > z)

### 1.3 Strings¶

In [ ]:

Copied!

```
# strings are represented using single or double quotes
first_name = "Adam"
last_name = 'Eve'
# \ is used to escape characters
middle_name = 'zero\'s'
# string concatenation
full_name = first_name +' ' + middle_name + ' ' + last_name
print(f"Full name is {full_name}")
print(f"Full name is of type {type(full_name)}")
# strings can be indexed and sliced similar to lists and tuples.
# List indexing is discussed in the list section
```

# strings are represented using single or double quotes
first_name = "Adam"
last_name = 'Eve'
# \ is used to escape characters
middle_name = 'zero\'s'
# string concatenation
full_name = first_name +' ' + middle_name + ' ' + last_name
print(f"Full name is {full_name}")
print(f"Full name is of type {type(full_name)}")
# strings can be indexed and sliced similar to lists and tuples.
# List indexing is discussed in the list section

In [ ]:

Copied!

```
# casting str to int
total = int('1') + int('2')
print(f"The value of total is {total} and it is of type {type(total)}")
# casting int to str
total = str(1) + str(2)
print(f"The value of total is {total} and it is of type {type(total)}")
```

# casting str to int
total = int('1') + int('2')
print(f"The value of total is {total} and it is of type {type(total)}")
# casting int to str
total = str(1) + str(2)
print(f"The value of total is {total} and it is of type {type(total)}")

### 1.4 Lists and Tuples¶

In [ ]:

Copied!

```
# Arrays are implemented as lists in python
# creating empty list
names = []
names = list()
# list of strings
names = ['Zach', 'Jay']
print(names)
# list of intergers
nums = [1, 2, 3, 4, 5]
print(nums)
# list of different data types
l = ['Zach', 1, True, None]
print(l)
# list of lists
ll = [[1, 3], [2, 3], [3, 4]]
# finding the length of list
length = len(l)
print(length)
```

# Arrays are implemented as lists in python
# creating empty list
names = []
names = list()
# list of strings
names = ['Zach', 'Jay']
print(names)
# list of intergers
nums = [1, 2, 3, 4, 5]
print(nums)
# list of different data types
l = ['Zach', 1, True, None]
print(l)
# list of lists
ll = [[1, 3], [2, 3], [3, 4]]
# finding the length of list
length = len(l)
print(length)

In [ ]:

Copied!

```
# Lists are mutable
names = names + ['Ravi']
names.append('Richard')
names.extend(['Abi', 'Kevin'])
print(names)
```

# Lists are mutable
names = names + ['Ravi']
names.append('Richard')
names.extend(['Abi', 'Kevin'])
print(names)

In [ ]:

Copied!

```
# List indexing and slicing
# an element or a subset of list can be accessed using element's index or slice of indices
# same notation applies for strings but at char level
# some_list[index]
# some_list[start_index: end_index(not included)]
numbers = [0, 1, 2, 3, 4, 5, 6]
# indices start from 0 in python
print(f'The first element in numbers is {numbers[0]}')
print(f'The third element in numbers is {numbers[2]}')
print(f'Elements from 1st to 5th index are {numbers[1:6]}')
print(f'Elements from start to 5th index are {numbers[:6]}')
print(f'Elements from 4th index to end are {numbers[4:]}')
print(f'Last Element is {numbers[-1]}')
print(f'Last four element are {numbers[-4:]}')
# changing 1st element in the numbers list
numbers[0] = 100
print(numbers)
# changing first 3 numbers
numbers[0: 3] = [100, 200, 300]
print(numbers)
```

# List indexing and slicing
# an element or a subset of list can be accessed using element's index or slice of indices
# same notation applies for strings but at char level
# some_list[index]
# some_list[start_index: end_index(not included)]
numbers = [0, 1, 2, 3, 4, 5, 6]
# indices start from 0 in python
print(f'The first element in numbers is {numbers[0]}')
print(f'The third element in numbers is {numbers[2]}')
print(f'Elements from 1st to 5th index are {numbers[1:6]}')
print(f'Elements from start to 5th index are {numbers[:6]}')
print(f'Elements from 4th index to end are {numbers[4:]}')
print(f'Last Element is {numbers[-1]}')
print(f'Last four element are {numbers[-4:]}')
# changing 1st element in the numbers list
numbers[0] = 100
print(numbers)
# changing first 3 numbers
numbers[0: 3] = [100, 200, 300]
print(numbers)

In [ ]:

Copied!

```
# Tuples are immutable lists. They are created using () instead of [].
names = tuple()
names = ('Zach', 'Jay')
print(names[0])
# trying to alter the tuple gives an error
names[0] = 'Richard'
# similar to tuples, strings are also immutable
```

# Tuples are immutable lists. They are created using () instead of [].
names = tuple()
names = ('Zach', 'Jay')
print(names[0])
# trying to alter the tuple gives an error
names[0] = 'Richard'
# similar to tuples, strings are also immutable

### 1.5 Dictionary¶

In [ ]:

Copied!

```
# hash maps in python are called Dictionaries
# dict{key: value}
# Empty dictionary
phonebook = dict()
# contruction dict using sequences of key-value pairs
dict([('sape', 4139), ('guido', 4127), ('jack', 4098)])
# Dictionary with one item
phonebook = {'jack': 4098}
# Add another item
phonebook['guido'] = 4127
print(phonebook)
print(phonebook['jack'])
print(phonebook.items())
print(phonebook.keys())
print(phonebook.values())
print('jack' in phonebook)
print('Kevin' in phonebook)
# Delete an item
del phonebook['jack']
print(phonebook)
```

# hash maps in python are called Dictionaries
# dict{key: value}
# Empty dictionary
phonebook = dict()
# contruction dict using sequences of key-value pairs
dict([('sape', 4139), ('guido', 4127), ('jack', 4098)])
# Dictionary with one item
phonebook = {'jack': 4098}
# Add another item
phonebook['guido'] = 4127
print(phonebook)
print(phonebook['jack'])
print(phonebook.items())
print(phonebook.keys())
print(phonebook.values())
print('jack' in phonebook)
print('Kevin' in phonebook)
# Delete an item
del phonebook['jack']
print(phonebook)

## 2. Flow control statements¶

### 2.1 if... elif... else...¶

In [ ]:

Copied!

```
# if expr1:
# code1
# elif expr2:
# code2
# .
# .
# .
# .
# else:
# code_n
# code1 is executed if expr1 is evaluated to true. Else it moves to expr2 and checks for true
# condition and moves to the next if not true.
# Finally if all the excpression's are false, code_n is executed
x = int(input("Please enter an integer: "))
if x < 0:
x = 0
print('Negative changed to zero')
elif x == 0:
print('Zero')
elif x == 1:
print('Single')
else:
print('More')
```

# if expr1:
# code1
# elif expr2:
# code2
# .
# .
# .
# .
# else:
# code_n
# code1 is executed if expr1 is evaluated to true. Else it moves to expr2 and checks for true
# condition and moves to the next if not true.
# Finally if all the excpression's are false, code_n is executed
x = int(input("Please enter an integer: "))
if x < 0:
x = 0
print('Negative changed to zero')
elif x == 0:
print('Zero')
elif x == 1:
print('Single')
else:
print('More')

## 3. Loops¶

### 3.1 For loops¶

In [ ]:

Copied!

```
# for loop is used to iter over any iterable object
# iterating over list
for name in ['Steve', 'Jill', 'Venus']:
print(name)
```

# for loop is used to iter over any iterable object
# iterating over list
for name in ['Steve', 'Jill', 'Venus']:
print(name)

In [ ]:

Copied!

```
# iterating over string
for char in "Hellooooo":
print(char)
```

# iterating over string
for char in "Hellooooo":
print(char)

In [ ]:

Copied!

```
# iterating over dict keys
phone_nos = {"Henry": 6091237458,
"James": 1234556789,
"Larry": 5698327549,
"Rocky": 8593876589}
for name, no in phone_nos.items():
print(name, no)
```

# iterating over dict keys
phone_nos = {"Henry": 6091237458,
"James": 1234556789,
"Larry": 5698327549,
"Rocky": 8593876589}
for name, no in phone_nos.items():
print(name, no)

In [ ]:

Copied!

```
# To iterate over a sequence of numbers we use range() function.
# range(start=0, end, step=1)
for i in range(2, 20, 2):
print(i)
```

# To iterate over a sequence of numbers we use range() function.
# range(start=0, end, step=1)
for i in range(2, 20, 2):
print(i)

In [ ]:

Copied!

```
# using len of list/tuple in range
names = ['Steve', 'Rock', 'Harry']
for i in range(len(names)):
print(names[i])
```

# using len of list/tuple in range
names = ['Steve', 'Rock', 'Harry']
for i in range(len(names)):
print(names[i])

#### 3.2 While Loop¶

In [ ]:

Copied!

```
# While loop executes as long as the condition remains true.
# while cond1:
# pass
i = 0
while i < 10:
print(i)
i += 1
```

# While loop executes as long as the condition remains true.
# while cond1:
# pass
i = 0
while i < 10:
print(i)
i += 1

In [ ]:

Copied!

```
# Forever loop: The below code runs for ever
# while True:
# print('Forever...')
```

# Forever loop: The below code runs for ever
# while True:
# print('Forever...')

#### 3.3 Break, Continue and Pass statements¶

In [ ]:

Copied!

```
# break statement breaks out of the the loop
while True:
print('We’re stuck in a loop...')
break # Break out of the while loop
print("not!")
```

# break statement breaks out of the the loop
while True:
print('We’re stuck in a loop...')
break # Break out of the while loop
print("not!")

In [ ]:

Copied!

```
# continue statement skips a loop
for i in range(5):
continue
print(i)
```

# continue statement skips a loop
for i in range(5):
continue
print(i)

In [ ]:

Copied!

```
# pass statement does nothing and is used as a placeholder
for i in range(10):
pass
```

# pass statement does nothing and is used as a placeholder
for i in range(10):
pass

## 4. Importing Modules¶

In [ ]:

Copied!

```
# importing modules using import statement
import math
# Import under an alias (avoid this pattern except with the most
# common modules like pandas, numpy, etc.)
import math as m
# Access components with pkg.fn
m.pow(2, 3)
# Import specific submodules/functions (not usually recommended
# because it can be confusing to know where a function comes from)
from math import pow
pow(2, 3)
```

# importing modules using import statement
import math
# Import under an alias (avoid this pattern except with the most
# common modules like pandas, numpy, etc.)
import math as m
# Access components with pkg.fn
m.pow(2, 3)
# Import specific submodules/functions (not usually recommended
# because it can be confusing to know where a function comes from)
from math import pow
pow(2, 3)

## 5. Defining Functions¶

In [ ]:

Copied!

```
# Functions in python are defined using key word "def"
# simple function to print greetings `greet_word` is an optional argument.
def greet(name, greet_word='Hello'):
print(f"{greet_word} {name}. How are you doing?")
# here greet has 'Hello' as default argument for greet_word
print(greet('James'))
print(greet("Steven", greet_word="Howdy"))
# Observe that the function by default returns None
```

# Functions in python are defined using key word "def"
# simple function to print greetings `greet_word` is an optional argument.
def greet(name, greet_word='Hello'):
print(f"{greet_word} {name}. How are you doing?")
# here greet has 'Hello' as default argument for greet_word
print(greet('James'))
print(greet("Steven", greet_word="Howdy"))
# Observe that the function by default returns None

In [ ]:

Copied!

```
# Function to print nth fibonacci number
def fib(n):
if n <= 1:
return 1
else:
return fib(n-1)+fib(n-2)
n = 10
print(f"{n}th fibonacci number is {fib(n)}")
```

# Function to print nth fibonacci number
def fib(n):
if n <= 1:
return 1
else:
return fib(n-1)+fib(n-2)
n = 10
print(f"{n}th fibonacci number is {fib(n)}")

## Questions¶

For each of the following question, first think about the result without running the code. Then test it by running the code. Reach out if you don't understand why!

### What's the output?¶

```
def func(a):
a = a + 2
a = a * 2
return a
print(func(2))
```

In [ ]:

Copied!

```
```

### True? False? Why?¶

```
0.1 + 0.2 == 0.3
```

In [ ]:

Copied!

```
# YOUR SOLUTION HERE
```

# YOUR SOLUTION HERE

### 3. What is `list_1`

and `list_2`

and why?¶

```
list_1 = [1,2,3]
list_2 = list_1
list_1.append(4)
list_2 += [5]
list_2 = list_2 + [10]
```

In [ ]:

Copied!

```
# YOUR SOLUTION HERE
```

# YOUR SOLUTION HERE

### What's the output?¶

```
l = [i**2 for i in range(10)]
l[-4:2:-3]
```

In [ ]:

Copied!

```
# YOUR SOLUTION HERE
```

# YOUR SOLUTION HERE

### What does the code do? If the ordering doesn't matter, how can it be simplified?¶

```
def func1(lst):
a = []
for i in lst:
if i not in a:
a.append(i)
return a
```

In [ ]:

Copied!

```
# YOUR SOLUTION HERE
```

# YOUR SOLUTION HERE

### What would be the output?¶

```
val = [0, 10, 15, 20]
data = 15
try:
data = data/val[0]
except ZeroDivisionError:
print("zero division error - 1")
except:
print("zero division error - 2")
finally:
print("zero division error - 3")
val = [0, 10, 15, 20]
data = 15
try:
data = data/val[4]
except ZeroDivisionError:
print("zero division error - 1")
except:
print("zero division error - 2")
finally:
print("zero division error - 3")
```

In [ ]:

Copied!

```
# YOUR SOLUTION HERE
```

# YOUR SOLUTION HERE

### What does the code do?¶

```
def func(s):
d = {}
for c in s:
if c in d:
d[n] += 1
else:
d[n] = 1
return d
```

(Btw, the same operation can be done by simply running `Counter(s)`

by using `Counter`

data structure in the `collections`

module.)

In [ ]:

Copied!

```
# YOUR SOLUTION HERE
```

# YOUR SOLUTION HERE

### What's the output?¶

```
def func(l):
l.append(10)
return l
a = [1,2,3]
b = func(a)
a == b
```

In [ ]:

Copied!

```
# YOUR SOLUTION HERE
```

# YOUR SOLUTION HERE

### What's happening to `a`

in each step? Why?¶

```
# step 1
a = [ [ ] ] * 5
# step 2
a[0].append(10)
# step 3
a[1].append(20)
# step 4
a.append(30)
```

In [ ]:

Copied!

```
# YOUR SOLUTION HERE
```

# YOUR SOLUTION HERE

### What's the output?¶

```
L = list('abcdefghijk')
L[1] = L[4] = 'x'
L[3] = L[-3]
print(L)
```

In [ ]:

Copied!

```
# YOUR SOLUTION HERE
```

# YOUR SOLUTION HERE

### What's the output?¶

```
y = 8
z = lambda x : x * y
print (z(6))
```

In [ ]:

Copied!

```
# YOUR SOLUTION HERE
```

# YOUR SOLUTION HERE

### What's the output?¶

```
count = 1
def func(count):
for i in (1, 2, 3):
count += 1
func(count = 10)
count += 5
print(count)
```

In [ ]:

Copied!

```
# YOUR SOLUTION HERE
```

# YOUR SOLUTION HERE