Table of Contents

1. Introduction to Python

Python3 is a multi-paradigm language, that combines the imperative style with the functional style. It also supports Object-Oriented programming, albeit in a limited way.

Python3 offers a few programming constructs that:

This lab will introduce some of these constructs.

List traversal

Exercise 1.1. Write a function f(l) which determines the maximum of a list l of integers.

The pythonic way

The pythonic way

Traversing a list using a for is done as follows:

for elem in collection:
    # do something

This idiom can be used for any collection not just lists, as you will discover during the lab.

Exercise 1.2. Modify the previous function to f(l,start,stop) and determine the maximum between positions start and stop.

The pythonic way

The pythonic way

When we care about the indices of a list, we can use the function range(x,y) which returns a list of integers starting from x until y-1.

for i in range(0,len(collection)):
    # do something with collection[i]

Slicing lists

Exercise 1.3. Find the longest sequence of positive integers from a list. E.g. for the list [1,3,-1,2,0,1,5,4,-2,4,5,-3,0,1,2] the answer is [2,0,1,5,4].

The pythonic way

The pythonic way

Python supports various list slicing operations, as well as “overloaded” indexing:

# the sublist from positions 0 to x of l:
l[0:x]
# the very same list:
l[:x]
# the last element of a list:
l[-1]
# the last three elements of a list:
l[-3:]
# the slice from n-3 to n-1, where n is the number of elements from the list
l[-3:-1]

Exercise 1.4. Write a pythonic function to check if a list is palindrome.

Other datatypes

The most widely used datatypes in Python are lists and dictionaries. Additionally, at LFA, we will also use: sets, stacks.

Stacks

In Python, lists are also used as stacks:

l = []
l.append(x)   # add x at the TOP of the stack (this will be the last element of the list)
l[-1]         # this is the top of the stack
x = l.pop()   # removes and returns an element from the top of the stack.

Exercise 1.5. Write a function which determines (and returns) the longest sequence of consecutive integers from a list.

Dictionaries

Python dictionaries are actually hash maps (or hash tables). The keys k are dispersed using a hash-function into buckets. Each bucket will hold its respective values. Some examples of dictionary usage:

#create an empty dictionary:
d = {}
 
#add or modify a key-value:
d[k]=v
 
#search if a key k is defined in a dictionary d:
if k in d:
  # do something

Exercise 1.6. Write a function which determines the number of occurrences of each character in a string.

The pythonic way

The pythonic way

def count(l):
   d = {}
   for x in l:
      if x in d:
         d[x] += 1
      else:
         d[x] = 1
   return d

Sets

Sets are collections where each element is unique. Sets can be traversed and indexed exactly as lists. They are initialised using the constructor set:

# the empty set:
s = set()
 
# set constructed from a list:
s = set([1,2,3])
 
# adding a new element to the set:
s.add(4)

Exercise 1.7. Determine the list of characters which occur in a string. E.g. for “limbajeformale” we have: “limbajefor”. (Hint 1: in Python there is no difference between a character and a singleton string and strings are just lists; Hint 2: to create a list from another object, use list()).

Pairs

Pairs are very similar to lists and can be substituted by the latter in many cases:

p = (x, y)     # a pair where the first element is x and the second is y
t = (x, y, z)  # a tuple
 
fst = p[0]
snd = p[1]
 
for k in t:
  # do something with element k of the tuple
 

The functional style

Higher-order functions and lambdas

The most used higher-order functions in Python are map and reduce:

from functools import reduce
 
# adds 1 to each element of a list
def allplus1(l):
   return map(lambda x:x+1,l)
 
# computes the sum of elements of a list
def sum_l (l):
   # inner functions are very useful for defining local, reusable functionality
   def plus(x,y):
      return x + y
   return reduce(plus,l) # reduce is a little different from Haskell folds: it does not use an initial value
 
def short_sum(l):
   return reduce(lambda x,y:x+y,l) # observe the syntax for lambdas

List comprehensions

List comprehensions are widely used programming tools in Python. Usage examples:

# adding 1 to each element of a list
l1 = [x+1 for x in [1,2,3]]
# [2,3,4]
 
# packing elements into pairs 
l2 = [(x,x+1) for x in [1,2,3]]
# [(1,2), (2,3), (3,4)]
 
# unpacking pairs in the for notation
l3 = [x+y for (x,y) in [(1,2), (2,3), (3,4)]]
# [3,5,7]
 
# combined list comprehensions
l4 = [(x,y) for x in [1,2,3] for y in [4,5,6]]
# [(1, 4), (1, 5), (1, 6), (2, 4), (2, 5), (2, 6), (3, 4), (3, 5), (3, 6)]
 
# filters
l5 = [x for x in [1,2,3,4] if x>2]
# [3,4]

Exercise 1.8. Write a function which takes a list of records first name, last name, CNP (encoded as tuples), and returns a list of the last names and ages of all females which are younger than the average of the entire list. E.g. [ (“Mary”, “Smith”, “2030602123456”), (“Anne”, “Doe”, “2121092123456”), (“Matei”, “Dan”, “1121202123456”), (“Maggie”, “Byrne”, “2121078123456”)] yields [(“Smith”,19), (“Doe”,29)]. Maggie was born in '78, whereas Mary, Anne and Matei were born in '94, '92 and 2002, respectively.

The pythonic way

The pythonic way

from functools import reduce
 
def getYouth(l):
	# this function computes the age of a given CNP
    def age(cnp):
        # conversion to integer of the two-character year code
        if int(cnp[5:8]) <= 21:
            return 2021 - int("20"+cnp[5:7])
        else:
            return 2021 - int("19"+cnp[5:7])
 
    # computing the average ages (a map could have also been used)
    avg = reduce(lambda a,b:a+b, [age(x[-1]) for x in l]) / len(l)
 
    # we return the last name and the age of the filtered list l
    return [(ln,age(cnp)) for (fn,ln,cnp) in l if cnp[0]=='2' and age(cnp) <= avg]

Practice

A labelled graph is encoded as a file where:

Example:

5
0 X 1
1 O 2 
1 X 3
1 O 4
4 X 1
3 O 2

Haskell practice

Solve the same exercise, only build your own input as a string, instead of a file.