Open In Colab

Lab 2: A one-lecture intro to Python#

The objective of this lecture is to give an overview of the Python programming language. We will discuss:

  • Variables & expressions

  • Basic data structures: list, tuple, and dict

  • Logic operations: if statement and for loops

  • Functions

  • Classes

  • Basic third-party packages for data science: numpy, pandas, and matplotlib (seaborn)

Getting help#

Shorcuts#

Menu bar: Help -> Show Keyboard Shortcut

  • e.g. m to change to a markdown, y to change to code cell, b to add a cell below

  • itself has a shortcut

Show available objects#

Typing dir() and passing in a module, function, method, variable or object shows the possible object, method and function calls available to that object. For example, we can investigate the different functions in the itertools module, which is part of Python’s Standard library.

import itertools
dir(itertools)
['__doc__',
 '__loader__',
 '__name__',
 '__package__',
 '__spec__',
 '_grouper',
 '_tee',
 '_tee_dataobject',
 'accumulate',
 'chain',
 'combinations',
 'combinations_with_replacement',
 'compress',
 'count',
 'cycle',
 'dropwhile',
 'filterfalse',
 'groupby',
 'islice',
 'pairwise',
 'permutations',
 'product',
 'repeat',
 'starmap',
 'takewhile',
 'tee',
 'zip_longest']

get help on a specific module, class, function, object …#

Typing help() and passing the module, class, function, object as the argument.

help(itertools.permutations)
Help on class permutations in module itertools:

class permutations(builtins.object)
 |  permutations(iterable, r=None)
 |  
 |  Return successive r-length permutations of elements in the iterable.
 |  
 |  permutations(range(3), 2) --> (0,1), (0,2), (1,0), (1,2), (2,0), (2,1)
 |  
 |  Methods defined here:
 |  
 |  __getattribute__(self, name, /)
 |      Return getattr(self, name).
 |  
 |  __iter__(self, /)
 |      Implement iter(self).
 |  
 |  __next__(self, /)
 |      Implement next(self).
 |  
 |  __reduce__(...)
 |      Return state information for pickling.
 |  
 |  __setstate__(...)
 |      Set state information for unpickling.
 |  
 |  __sizeof__(...)
 |      Returns size in memory, in bytes.
 |  
 |  ----------------------------------------------------------------------
 |  Static methods defined here:
 |  
 |  __new__(*args, **kwargs) from builtins.type
 |      Create and return a new object.  See help(type) for accurate signature.

Docs on the fly#

You can get a popup window showing the documentation of a module, class, function, object. Type the name of the module, class, function, object, and then press Shift+Tab.

itertools   # press `Shift+Tab`
<module 'itertools' (built-in)>
itertools.permutations  # press `Shift+Tab`
itertools.permutations

Variables#

x = 1 
y = 2 
z = x + y

z
3
print(z)
3

Variable can be reassigned new values

x = 3.0
y = 4.0 

z = x + y

z
7.0

Data types#

  • Python is a dynamic language without the need to specify data type at definition.

  • Type hint is strongly encouraged, although it is ignored by the interpreter.

x: int = 1 
y: float = 2.0 
z = x+y

z
3.0
type(z)
float
x = 'Hello '
y = 'Cougars'

x+y 
'Hello Cougars'
x: int = 1 
y: float = 2
z = x+y

Q: What is the type of z? int or float?

z
3
type(z)
int

List#

a = [1, 2, 3]

print(a)
[1, 2, 3]
type(a)
list

Elements can be any data types

a = [1, 'hello', [3, 'cougars'], 0]

Elements can be assessed via indices (0 based)

a[0]
1
a[3]
0

List is mutable

a[0] = 'updated'

a
['updated', 'hello', [3, 'cougars'], 0]
a.append('cool')
a
['updated', 'hello', [3, 'cougars'], 0, 'cool']

Tuple#

a = (1, 'hello', 2.0, [3, 'cougars'])

Like list, element of tuple can be assessed via indices

a[0]
1
a[3]
[3, 'cougars']

Difference from list: tuple is immutable

# a[0] = 'updated'

Dict#

  • key–value pairs (maps)

  • only immutable can be used as key

  • value can be anything

d = {'first': 'Guido', 'last': 'van Rossum', 'age': 67}
d['first']
'Guido'
d  = {1: 'Guido', 2: 'van Rossum'}
d = {(1, 2): 'Guido', 2: 'van Rossum'}
# d = {[1,2]: 'Guido', 2: 'van Rossum'}

If statement#

x = 3
# x = 2
# x = 3.5

if x%2 == 0:
    print(x, 'is an even number')
elif x%2 == 1:
    print(x, 'is an odd number')
else:
    print(x, 'is neither an even nor an odd number')
3 is an odd number

For loops#

a = [1, 'hello', [3, 'cougars'], 0]

for x in a:
    print(x)
1
hello
[3, 'cougars']
0
for i,x in enumerate(a):
    print(i, x)
0 1
1 hello
2 [3, 'cougars']
3 0
d = {'first': 'Guido', 'last': 'van Rossum', 'age': 67}

for k in d:
    print(k)
    print(d[k])
first
Guido
last
van Rossum
age
67
for k, v in d.items():
    print('Key:', k, 'Value:', v)
Key: first Value: Guido
Key: last Value: van Rossum
Key: age Value: 67

While loop

a = ['a', 'b', 'c']

length = len(a)

length
3
i = 0

while i < length:
    print(a[i])
    i += 1 
a
b
c

Function#

def add(a:int, b:int):
    return a+b
y = add(1, 2)
y
3
y = add(3, 4)
y
7

Arguments can take default values

def add(a:int, b:int = 1):
    return a+b

add(2)
3

A (a bit) more complex example

def get_even_numbers(data: list[int]):
    even = []
    for i in data:
        if i%2 == 0:
            even.append(i)
    
    return even
get_even_numbers([1,2,4,5,8])
[2, 4, 8]

Class#

  • Bundle data and operations on data together

class IntegerSelector:

    def __init__(self, data):
        self.data = data

    def get_even_numbers(self):
        selected = []
        for i in self.data:
            if i%2 == 0:
                selected.append(i)
        return selected

    def get_odd_numbers(self):
        selected = []
        for i in self.data:
            if i%2 == 1:
                selected.append(i)
        return selected

    def count_number_of_elements(self):
        return len(self.data)

    def get_even_divide_by_n(self, n=2):
        selected = []
        for i in self.data:
            if i%n == 0:
                selected.append(i)
        return selected
selector = IntegerSelector([1,2,3,4,5,6])
selector.get_even_numbers()
[2, 4, 6]
selector.get_odd_numbers()
[1, 3, 5]
selector.count_number_of_elements()
6
selector.get_even_divide_by_n(n=3)
[3, 6]

Numpy#

Numpy allows for easy handling high-dimensional arrays, along with a large collection of high-level mathematical functions to operate on these array

import numpy as np
a = np.array([[1,2,3,
               4,5,6,
               7,8,9]])

a
array([[1, 2, 3, 4, 5, 6, 7, 8, 9]])
np.arange(9).reshape((3,3))
array([[0, 1, 2],
       [3, 4, 5],
       [6, 7, 8]])
np.eye
<function numpy.eye(N, M=None, k=0, dtype=<class 'float'>, order='C', *, like=None)>
def compute_mae(a, b):
    a = np.asarray(a)
    b = np.asarray(b)

    diff =  a - b
    abs_diff = np.abs(diff)
    result = np.mean(abs_diff)

    return result
pred =  [1,1,1]
ref =  [2,2,0]
compute_mae(pred, ref)
1.0

Matplotlib#

  • A plotting library that can create (almost) all kinds of scientific plots you want.

  • If you are familiar with matlab plotting, matplotlib should be familiar.

  • Matplotlib cheatsheets: matplotlib/cheatsheets

  • Check out seaborn as well, which provides high-level API to generate beautiful plots.

import matplotlib.pyplot as plt
fig , ax = plt.subplots()

x = [1, 2, 3, 4, 5]
y = [2, 4, 6, 7, 8]

ax.scatter(x, y, color='C0')


a = np.linspace(0, 2*np.pi, 100)
b = np.sin(a)

ax.plot(a, b, color='C1')


ax.annotate('max',  xytext=(2, 2), xy = (np.pi/2, 1),
            arrowprops=dict(arrowstyle="->"),
            )

ax.annotate('min',  xytext=(4, 2), xy = (np.pi/2*3, -1),
            arrowprops=dict(arrowstyle="->"),
            )

ax.set_xlabel('Reference')
ax.set_ylabel('Prediction')



fig.savefig('sine_plot.pdf')
../_images/6e6f295d2494efa8d4a2e89839e41a9b9882ace424d7ea02fe8b0bbca7d2e666.png