1. Day 1 - Lecture 1#

  • Part 0: Why Python?

  • Part 1: Variables, Types, and Operations

  • Part 2: Lists

  • Part 3: Conditional statements

  • Part 4: Loops

  • Part 5: Dictionaries

1.1. Why Coding and Python?#

  • Great for data processing and simulations

  • Coding is fast at dealing with large amounts of data and math

  • Python, very versatile and popular

  • Very active community developing libraries for it

  • One of the more user beginner friendly languages

  • Skills transfer to other languages

The goal of this workshop is to teach you the practical basics and fundamentals, but also show you how to access resources and teach yourself.

1.2. Part 1: Variables, Types, and Operations#

Variables are the building blocks of software, taking on assigned values that can be used later in the code or updated.

Python is an object oriented programming language. All values are represented as certain types of objects.

Types:

  • Integers

  • Floats (decimals)

  • Strings (text)

  • Many more

Working with Integers and Floats:

a = 4
b = 4.0
c = 'A String'

print(a)
print(a, b)
print(c)
print(type(a), type(b), type(c))
4
4 4.0
A String
<class 'int'> <class 'float'> <class 'str'>

Variable names can contain underscores and numbers, but cannot begin with a number

var_1 = 0
print(var_1)
0
1var = 0
  File "<ipython-input-3-c4ff8223a544>", line 1
    1var = 0
     ^
SyntaxError: invalid syntax

The variables (and objects) can be operated on with common “operators”. For numbers we have:

( + ) Addition
( - ) Subtracton
( * ) Multiplication
( / ) Division
( ** ) Exponentiation

f1 = 2.5
f2 = 4.0

f_added = f1 + f2
f_subtracted = f1 - f2
f_multiplied = f1 * f2
f_divided = f1 / f2
f2_cubed = f2 ** 3

print(f_added)
print(f_subtracted)
print(f_multiplied)
print(f_divided)
print(f2_cubed)
6.5
-1.5
10.0
0.625
64.0

There is shorthand notation for updating a variable with an operation:

f3 = 10
f3 = f3 + 5
print(f3)

f3 = 10
f3 += 5
print(f3)

f4 = 10
f4 *= 5
print(f4)
15
15
50

Types are often managed automatically by the Python interpreter.

a = 5
b = 1.5
print(type(a), type(b))

c = a * b
print(c, type(c))
<class 'int'> <class 'float'>
7.5 <class 'float'>

Working with Strings:

s1 = 'A String'
s2 = "Another String"
s3 = '''A longer string,
written on multiple lines'''
print(s1)
print(s2)
print(s3)
A String
Another String
A longer string,
written on multiple lines

There are several methods available to operate on strings. Some are demonstrated here:

s1 = s1.replace('A', 'One')
s2 = s2.replace('n', 'N')

print(s1)
print(s2)
print(s2.lower())
print(s2.upper())
One String
ANother StriNg
another string
ANOTHER STRING
s1 = 'A'
s2 = 'String'

print(s1 + s2)
print(s1 + ' ' + s2)
AString
A String

Strings can be formatted with other variables.

name = 'Ben'
num = 2
sentence = '{} ate {} cupcakes.'
print(sentence)
print(sentence.format(name, num))

sentence = f'{name} ate {num} cupcakes.'
print(sentence)
{} ate {} cupcakes.
Ben ate 2 cupcakes.
Ben ate 2 cupcakes.

1.3. Part 2: Lists#

Lists are containers for storing a collecition of objects. Items can be appended to the list, inserted into a specific posiiton, removed, or “popped” from a specific position

my_list = []
print(my_list)

my_list.append(1)
print(my_list)

my_list.append(2)
my_list.append(3)
my_list.append(4)
print(my_list)

my_list.insert(0, 10)
print(my_list)

my_list.remove(1)
print(my_list)

popped_value = my_list.pop()
print(popped_value, my_list)

popped_value = my_list.pop(0)
print(popped_value, my_list)
[]
[1]
[1, 2, 3, 4]
[10, 1, 2, 3, 4]
[10, 2, 3, 4]
4 [10, 2, 3]
10 [2, 3]

Indexing lists (selecting the elements from inside a list) is performed with the square brackets [].

my_list = [1, 2, 3, 4, 5, 6]
print(my_list[0])
print(my_list[1])
1
2

Of course, a list cannot be indexed beyond its final element.

print(my_list[7])
---------------------------------------------------------------------------
IndexError                                Traceback (most recent call last)
Input In [27], in <cell line: 1>()
----> 1 print(my_list[7])

IndexError: list index out of range

Multiple subsequent elements can be selected with a “slice”, represented by the colon :
The slice takes the form [start:end:step].
Leaving start (end) blank implies the first (last) element. The step size defaults to 1 if not included.

print(my_list[:])
print(my_list[::])

list_slice1 = my_list[2:5] # Select the 3rd, 4th, and 5th element
print(list_slice1)

list_slice2 = my_list[::2] # Select elements from the beginning to end with step size 2
print(list_slice2)
[1, 2, 3, 4, 5, 6]
[1, 2, 3, 4, 5, 6]
[3, 4, 5]
[1, 3, 5]

Certain symbolic operators also work on lists, like + and *.

numbers = [45, 21, 33]
more_numbers = [100, 3, 56]
all_numbers = numbers + more_numbers
print(all_numbers)

letters = ['A', 'f', 'Z']
multiplied_list = letters * 3
print(multiplied_list)
[45, 21, 33, 100, 3, 56]
['A', 'f', 'Z', 'A', 'f', 'Z', 'A', 'f', 'Z']

1.4. Part 3: Conditional Statements#

The flow of logic through a program is controlled through conditional statements, also known as “if” statements.

Code inside of an “if” block is executed depending on a boolean (true or false) condition.
An “if” block can be followed by an “elif” conditional, which is checked only if the leading “if” evalutates false.
An “else” block can follow any number of “if” or “elif” blocks.

Boolean operators:

  • > Greater than

  • < Less than

  • >= Greater than or equal to

  • <= Less than or equal to

  • == Equal to

  • != Does not equal

  • “not” Takes the opposite of a boolean statement

  • “and” Requires both joined boolean statements to be true

  • “or” Requires one of joined boolean statements to be true

x,y = 4,5

if x == y:
    print(f'{x} is equal to {y}')
elif x > y:
    print(f'{x} is greater than {y}')
else:
    print(f'{x} is not equal to {y}, and {x} is not greater than {y}')

if x <= y:
    print(f'{x} is less than {y}')
elif x*y == 20:
    print(f'{x} times {y} equals 20')

if x == y or x*y == 20:
    xy = x * y
    print(f'Either {x} equals {y}, or {x} times {y} equals {20}')

if x < y and x*y == 20:
    print(f'{x} is less than {y}, and {x} times {y} equals {20}')


s1 = 'Hello'
s2 = 'Jelly'

if s1 == s2:
    print(f'{s1} is equal to {s2}')
elif len(s1) == len(s2):
    print(f'The words {s1} and {s2} have the same number of characters')

s2 = s2.replace('J', 'H').replace('y', 'o')
if s1 == s2:
    print(f'{s1} is equal to {s2}')
4 is not equal to 5, and 4 is not greater than 5
4 is less than 5
Either 4 equals 5, or 4 times 5 equals 20
4 is less than 5, and 4 times 5 equals 20
The words Hello and Jelly have the same number of characters
Hello is equal to Hello

1.5. Part 4: Loops#

Loops provide a way of repeating a block of code many times. The loop will run across successive values of an “iterable”. Iterables are objects with an ordered set of items: range, lists

for i in range(10):
    print(i, i*8)
0 0
1 8
2 16
3 24
4 32
5 40
6 48
7 56
8 64
9 72

Loops are often useful for iterating over values in a list, or proccessing multiple data points in the same way without repeating code.

num_candies = [7, 4, 3, 6]

for nc in num_candies:
    print(nc)
7
4
3
6
for i,nc in enumerate(num_candies):
    print(f'There are {nc} candies in jar {i}.')
There are 7 candies in jar 0.
There are 4 candies in jar 1.
There are 3 candies in jar 2.
There are 6 candies in jar 3.

What if we want to sum up all elements of a list?

total_candies = num_candies[0] + num_candies[1] + num_candies[2] + num_candies[3]
print(total_candies)
20
total_candies = 0
for nc in num_candies:
    total_candies += nc
print(total_candies)
20

What if one wants to compare all possible pairs of numbers in a list?
We can use nested for loops to achieve this.

numbers = [1, 3, 5, 7, 9]

for n1 in numbers:
    for n2 in numbers:
        product = n1 * n2
        print(f'The product of {n1} and {n2} is {product}.')
The product of 1 and 1 is 1.
The product of 1 and 3 is 3.
The product of 1 and 5 is 5.
The product of 1 and 7 is 7.
The product of 1 and 9 is 9.
The product of 3 and 1 is 3.
The product of 3 and 3 is 9.
The product of 3 and 5 is 15.
The product of 3 and 7 is 21.
The product of 3 and 9 is 27.
The product of 5 and 1 is 5.
The product of 5 and 3 is 15.
The product of 5 and 5 is 25.
The product of 5 and 7 is 35.
The product of 5 and 9 is 45.
The product of 7 and 1 is 7.
The product of 7 and 3 is 21.
The product of 7 and 5 is 35.
The product of 7 and 7 is 49.
The product of 7 and 9 is 63.
The product of 9 and 1 is 9.
The product of 9 and 3 is 27.
The product of 9 and 5 is 45.
The product of 9 and 7 is 63.
The product of 9 and 9 is 81.

Here, each comparison between non-identical numbers is performed twice, which is a waste of time. This can be avoided by forcing the inner for loop to pick up where the outer loop leaves off.

for i1,n1 in enumerate(numbers):
    for n2 in numbers[i1:]:
        product = n1 * n2
        print(f'The product of {n1} and {n2} is {product}.')
The product of 1 and 1 is 1.
The product of 1 and 3 is 3.
The product of 1 and 5 is 5.
The product of 1 and 7 is 7.
The product of 1 and 9 is 9.
The product of 3 and 3 is 9.
The product of 3 and 5 is 15.
The product of 3 and 7 is 21.
The product of 3 and 9 is 27.
The product of 5 and 5 is 25.
The product of 5 and 7 is 35.
The product of 5 and 9 is 45.
The product of 7 and 7 is 49.
The product of 7 and 9 is 63.
The product of 9 and 9 is 81.

1.6. Part 5: Dictionaries#

Dictionaries are collections of key-value pairs, in a “hash map”.
They provide a very fast method of mapping or storing values under a key.

person = {}
person['name'] = 'Frank'
person['age'] = 30
print(person)
print(person['name'])

person = {'name':'Frank', 'age':30}
person['address'] = '123 Best Avenue'
print(person)
{'name': 'Frank', 'age': 30}
Frank
{'name': 'Frank', 'age': 30, 'address': '123 Best Avenue'}

Dictionaries are useful for many applications. One use case is counting occurance frequency objects in a list.

values = [1, 3, 2, 3, 1, 1, 4, 3, 2, 2, 1, 3, 1, 3]

counts = {}
for v in values:
    if v not in counts:
        counts[v] = 0
    counts[v] += 1

print(counts)
print(counts[1])
print(counts[4])
{1: 5, 3: 5, 2: 3, 4: 1}
5
1