Lab 02

Download as pdf or txt
Download as pdf or txt
You are on page 1of 47

ICE-4101 – Introduction to Programming Semester 1 - Laboratory 2

ICE-4101

Laboratory 2: More Python

School of Computer Science and Elec. Eng,, Bangor University 1 2022 / 2023
ICE-4101 – Introduction to Programming Semester 1 - Laboratory 2

EXERCISES
For this module’s laboratory session, you will need to submit a report in Blackboard that includes the
answers to each of the lab exercises. You will have two weeks to complete the report. Marks (out of
100) are shown at the top of each exercise. Try to complete the exercises within the two lab sessions
otherwise you will need to complete the exercises in your own time. There will be four labs for this
module, so as the lab weighting is 40%, each lab report is worth 10%.

SUBMISSION DEADLINE
All lab work will be due at midnight on Thursday of the week when it is due.

DOCUMENTATION
Official Python website – Python.org:

http://www.python.org/

Much of the following material is taken from the following Website:

http://www.python.org/doc/current/tut/tut.html

For further information and documentation, you can also try the Python Wiki:

http://wiki.python.org/moin/

O’Reilly Media – “Learning Python” :

http://oreilly.com/catalog/9780596513986/

School of Computer Science and Elec. Eng,, Bangor University 2 2022 / 2023
ICE-4101 – Introduction to Programming Semester 1 - Laboratory 2

MORE ON DEFINING FUNCTIONS

It is also possible to define functions with a variable number of arguments. There are three
forms, which can be combined.

DEFAULT ARGUMENT VALUES

The most useful form is to specify a default value for one or more arguments. This creates a
function that can be called with fewer arguments than it is defined to allow. For example:

def ask_ok(prompt, retries=4, complaint='Yes or no, please!'):

while True:

ok = input(prompt)

if ok in ('y', 'ye', 'yes'): return True

if ok in ('n', 'no', 'nop', 'nope'): return False

retries = retries - 1

if retries < 0: raise (IOError, 'refusenik user')

print (complaint)

This function can be called either like this: ask_ok('Do you really want to
quit?') or like this: ask_ok('OK to overwrite the file?', 2).

This example also introduces the in keyword. This tests whether or not a sequence contains a
certain value.

The default values are evaluated at the point of function definition in the defining scope, so
that

i = 5

def f(arg=i):

print (arg)

i = 6
School of Computer Science and Elec. Eng,, Bangor University 3 2022 / 2023
ICE-4101 – Introduction to Programming Semester 1 - Laboratory 2

f()

will print 5.

Important warning: The default value is evaluated only once. This makes a difference when
the default is a mutable object such as a list, dictionary, or instances of most classes. For
example, the following function accumulates the arguments passed to it on subsequent
calls:

def f(a, L=[]):

L.append(a)

return L

print (f(1))

print (f(2))

print (f(3))

This will print

[1]

[1, 2]

[1, 2, 3]

If you don't want the default to be shared between subsequent calls, you can write the
function like this instead:

def f(a, L=None):

if L is None:

L = []

L.append(a)

return L

4.7.2 KEYWORD ARGUMENTS

School of Computer Science and Elec. Eng,, Bangor University 4 2022 / 2023
ICE-4101 – Introduction to Programming Semester 1 - Laboratory 2

Functions can also be called using keyword arguments of the form "keyword = value". For
instance, the following function:

def parrot(voltage, state='a stiff', action='voom',


type='Norwegian Blue'):

print ("-- This parrot wouldn't", action, end = '')

print (" if you put", voltage, "volts through it.")

print ("-- Lovely plumage, the", type)

print ("-- It's", state, "!")

could be called in any of the following ways:

parrot(1000)

parrot(action = 'VOOOOOM', voltage = 1000000)

parrot('a thousand', state = 'pushing up the daisies')

parrot('a million', 'bereft of life', 'jump')

but the following calls would all be invalid:

parrot() # required argument missing

parrot(voltage=5.0, 'dead') # non-keyword argument following


keyword

parrot(110, voltage=220) # duplicate value for argument

parrot(actor='John Cleese') # unknown keyword

EXERCISE 2.1 – U.S.A. PRESIDENTS (15 MARKS)

This exercise will explore the different ways you can specify arguments to a function.

For this exercise, first define the following function and then answer the following questions
in Blackboard.

def president(D_votes, R_votes, current=' Donald Trump',


D_nominee='Joe Biden', R_nominee='Donald Trump'):
print ("The current president of U.S.A. is ", current,
end = '')

School of Computer Science and Elec. Eng,, Bangor University 5 2022 / 2023
ICE-4101 – Introduction to Programming Semester 1 - Laboratory 2

if (D_votes > R_votes):


print ("The new president will be ", D_nominee)
else:
print ("The new president will be ", R_nominee)

[1 mark for each of the following]

Q1 Enter the output produced when you type in the following:

president (274, 264)

Q2 Enter the output produced when you type in the following:

president (332, 206, D_nominee = "Elizabeth Warren", R_nominee =


"Mike Pence")

Q3 Enter the code you would type if the Democratic nominee was
Hillary Clinton and the Republican nominee was Mitt Romney and the
number of electoral votes for the Democrats was 270 and for the
Republicans was 268. [3 marks]

[2 marks for each of following Questions Q4 to Q8]

Choices for Questions Q4 to Q8:

A. The code is correct because it does not produce a run-time


error

B. The code produces a run-time error because a required argument


is missing

C. The code produces a run-time error because there is a non-


keyword argument following a keyword

D. The code produces a run-time error because there is a duplicate


value for an argument

E. The code produces a run-time error because there is an unknown


keyword

Q4 [Multi-choice question] Select the correct choice (from the above


list) that describes the output produced when you type in the
following:

president (278)

Q5 [Multi-choice question] Select the correct choice (from the above


list) that describes the output produced when you type in the
following:

president (264, 274, D_votes = 320)

School of Computer Science and Elec. Eng,, Bangor University 6 2022 / 2023
ICE-4101 – Introduction to Programming Semester 1 - Laboratory 2

Q6 [Multi-choice question] Select the correct choice (from the above


list) that describes the output produced when you type in the
following:

president (D_votes = 278, 260)

Q7 [Multi-choice question] Select the correct choice (from the above


list) that describes the output produced when you type in the
following:

president (R_votes=268, D_votes=274)

Q8 [Multi-choice question] Select the correct choice (from the above


list) that describes the output produced when you type in the
following:

president (274, 268, Current = "George Bush")

In general, an argument list must have any positional arguments followed by any keyword
arguments, where the keywords must be chosen from the formal parameter names. It's not
important whether a formal parameter has a default value or not. No argument may receive
a value more than once -- formal parameter names corresponding to positional arguments
cannot be used as keywords in the same calls. Here's an example that fails due to this
restriction:

>>> def function(a):

... pass

...

>>> function(0, a=0)

Traceback (most recent call last):

File "<stdin>", line 1, in ?

TypeError: function() got multiple values for keyword argument


'a'

When a final formal parameter of the form **name is present, it receives a dictionary
containing all keyword arguments except for those corresponding to a formal parameter.
This may be combined with a formal parameter of the form *name (described in the next
subsection) which receives a tuple containing the positional arguments beyond the formal
parameter list. (*name must occur before **name.) For example, if we define a function like
this:

School of Computer Science and Elec. Eng,, Bangor University 7 2022 / 2023
ICE-4101 – Introduction to Programming Semester 1 - Laboratory 2

def cheeseshop(kind, *arguments, **keywords):

print ("-- Do you have any", kind, '?')

print ("-- I'm sorry, we're all out of", kind)

for arg in arguments: print (arg)

print ('-'*40)

keys = keywords.keys()

keys.sort()

for kw in keys: print (kw, ':', keywords[kw])

It could be called like this:

cheeseshop('Limburger', "It's very runny, sir.",

"It's really very, VERY runny, sir.",

client='John Cleese',

shopkeeper='Michael Palin',

sketch='Cheese Shop Sketch')

and of course it would print:

-- Do you have any Limburger ?

-- I'm sorry, we're all out of Limburger

It's very runny, sir.

It's really very, VERY runny, sir.

----------------------------------------

client : John Cleese

shopkeeper : Michael Palin

sketch : Cheese Shop Sketch

Note that the sort() method of the list of keyword argument names is called before
printing the contents of the keywords dictionary; if this is not done, the order in which the
arguments are printed is undefined.

School of Computer Science and Elec. Eng,, Bangor University 8 2022 / 2023
ICE-4101 – Introduction to Programming Semester 1 - Laboratory 2

ARBITRARY ARGUMENT LISTS

Finally, the least frequently used option is to specify that a function can be called with an
arbitrary number of arguments. These arguments will be wrapped up in a tuple. Before the
variable number of arguments, zero or more normal arguments may occur.

def fprintf(file, format, *args):

file.write(format % args)

UNPACKING ARGUMENT LISTS

The reverse situation occurs when the arguments are already in a list or tuple but need to be
unpacked for a function call requiring separate positional arguments. For instance, the built-
in range() function expects separate start and stop arguments. If they are not available
separately, write the function call with the *-operator to unpack the arguments out of a list
or tuple:

>>> range(3, 6) # normal call with separate


arguments

[3, 4, 5]

>>> args = [3, 6]

>>> range(*args) # call with arguments unpacked


from a list

[3, 4, 5]

In the same fashion, dictionaries can deliver keyword arguments with the **-operator:

>>> def parrot(voltage, state='a stiff', action='voom'):

... print ("-- This parrot wouldn't", action, end = '')

... print ("if you put", voltage, "volts through it.", end
= '')

... print ("E's", state, "!")

...

School of Computer Science and Elec. Eng,, Bangor University 9 2022 / 2023
ICE-4101 – Introduction to Programming Semester 1 - Laboratory 2

>>> d = {"voltage": "four million", "state": "bleedin'


demised", "action": "VOOM"}

>>> parrot(**d)

-- This parrot wouldn't VOOM if you put four million volts


through it. E's bleedin' demised !

DATA STRUCTURES

This section describes some things you've learned about already in more detail, and adds
some new things as well.

MORE ON LISTS

The list data type has some more methods. Here are all of the methods of list objects:

append(x)

Add an item to the end of the list; equivalent to a[len(a):] = [x].

extend(L)

Extend the list by appending all the items in the given list; equivalent to a[len(a):]
= L.

insert(i, x)

Insert an item at a given position. The first argument is the index of the element before
which to insert, so a.insert(0, x) inserts at the front of the list, and
a.insert(len(a), x) is equivalent to a.append(x).

remove(x)

Remove the first item from the list whose value is x. It is an error if there is no such
item.

pop([i])

Remove the item at the given position in the list, and return it. If no index is specified,
a.pop() removes and returns the last item in the list. (The square brackets around
the i in the method signature denote that the parameter is optional, not that you

School of Computer Science and Elec. Eng,, Bangor University 10 2022 / 2023
ICE-4101 – Introduction to Programming Semester 1 - Laboratory 2

should type square brackets at that position. You will see this notation frequently in
the Python Library Reference.)

index(x)

Return the index in the list of the first item whose value is x. It is an error if there is no
such item.

count(x)

Return the number of times x appears in the list.

sort()

Sort the items of the list, in place.

reverse()

Reverse the elements of the list, in place.

An example that uses most of the list methods:

>>> a = [66.25, 333, 333, 1, 1234.5]

>>> print (a.count(333), a.count(66.25), a.count('x'))

2 1 0

>>> a.insert(2, -1)

>>> a.append(333)

>>> a

[66.25, 333, -1, 333, 1, 1234.5, 333]

>>> a.index(333)

>>> a.remove(333)

>>> a

[66.25, -1, 333, 1, 1234.5, 333]

>>> a.reverse()

>>> a

School of Computer Science and Elec. Eng,, Bangor University 11 2022 / 2023
ICE-4101 – Introduction to Programming Semester 1 - Laboratory 2

[333, 1234.5, 1, 333, -1, 66.25]

>>> a.sort()

>>> a

[-1, 1, 66.25, 333, 333, 1234.5]

USING LISTS AS S TACKS

The list methods make it very easy to use a list as a stack, where the last element added is
the first element retrieved (“last-in, first-out”). To add an item to the top of the stack, use
append(). To retrieve an item from the top of the stack, use pop() without an explicit
index. For example:

>>> stack = [3, 4, 5]

>>> stack.append(6)

>>> stack.append(7)

>>> stack

[3, 4, 5, 6, 7]

>>> stack.pop()

>>> stack

[3, 4, 5, 6]

>>> stack.pop()

>>> stack.pop()

>>> stack

[3, 4]

USING LISTS AS QUEUES

School of Computer Science and Elec. Eng,, Bangor University 12 2022 / 2023
ICE-4101 – Introduction to Programming Semester 1 - Laboratory 2

You can also use a list conveniently as a queue, where the first element added is the first
element retrieved (“first-in, first-out”). To add an item to the back of the queue, use
append(). To retrieve an item from the front of the queue, use pop() with 0 as the index.
For example:

>>> queue = ["Eric", "John", "Michael"]

>>> queue.append("Terry") # Terry arrives

>>> queue.append("Graham") # Graham arrives

>>> queue.pop(0)

'Eric'

>>> queue.pop(0)

'John'

>>> queue

['Michael', 'Terry', 'Graham']

FUNCTIONAL PROGRAMMING TOOLS

There are three functions that are very useful when used with lists: filter(), map(), and
reduce(). To get these functions, import the functools module first:

import functools

"filter(function, sequence)" returns a sequence consisting of those items from the


sequence for which function(item) is true. If sequence is a string or tuple, the result will
be of the same type; otherwise, it is always a list. For example, to compute some primes:

>>> def f(x): return x % 2 != 0 and x % 3 != 0

...

>>> list(filter(f, range(2, 25)))

[5, 7, 11, 13, 17, 19, 23]

"map(function, sequence)" calls function(item) for each of the sequence's items and returns
a list of the return values. For example, to compute some cubes:

>>> def cube(x): return x*x*x


School of Computer Science and Elec. Eng,, Bangor University 13 2022 / 2023
ICE-4101 – Introduction to Programming Semester 1 - Laboratory 2

...

>>> list(map(cube, range(1, 11)))

[1, 8, 27, 64, 125, 216, 343, 512, 729, 1000]

More than one sequence may be passed; the function must then have as many arguments as
there are sequences and is called with the corresponding item from each sequence (or None
if some sequence is shorter than another). For example:

>>> seq = range(8)

>>> def add(x, y): return x+y

...

>>> list(map(add, seq, seq))

[0, 2, 4, 6, 8, 10, 12, 14]

"reduce(function, sequence)" returns a single value constructed by calling the binary


function function on the first two items of the sequence, then on the result and the next
item, and so on. For example, to compute the sum of the numbers 1 through 10:

>>> def add(x,y): return x+y

...

>>> reduce(add, range(1, 11))

55

If there's only one item in the sequence, its value is returned; if the sequence is empty, an
exception is raised.

A third argument can be passed to indicate the starting value. In this case the starting value
is returned for an empty sequence, and the function is first applied to the starting value and
the first sequence item, then to the result and the next item, and so on. For example,

>>>from functools import reduce

>>> def sum(seq):

... def add(x,y): return x+y

... return reduce(add, seq)

...
School of Computer Science and Elec. Eng,, Bangor University 14 2022 / 2023
ICE-4101 – Introduction to Programming Semester 1 - Laboratory 2

>>> sum(range(1, 11))

55

>>> sum([1,2])

>>> sum([1,22])

23

Don't use this example's definition of sum(): since summing numbers is such a common
need, a built-in function sum(sequence) is already provided, and works exactly like this.

EXERCISE 2.2 – PRODUCTS (14 MARKS)

In this exercise, you will modify the above function code to return the product of the items
on the list rather than the sum.

There are three lines of code in the above program:

>>>from functools import reduce

Line 1: >>> def sum(seq):

Line 2: ... def add(x,y): return x+y

Line 3: ... return reduce(add, seq)

For your modified function, you will need to use the exact same number of lines of code.

[Note: In the answers you submit below, do not include any indentation in your code. Use
appropriate function names and similar spacing as above.]

Q9 Enter the code in your new program for Line 1. [3 marks]

Q10 Enter the code in your new program for Line 2. [3 marks]

Q11 Enter the code in your new program for Line 3. [3 marks]

School of Computer Science and Elec. Eng,, Bangor University 15 2022 / 2023
ICE-4101 – Introduction to Programming Semester 1 - Laboratory 2

Q12 Enter the code you would type to run your new function to return
the product of the numbers 10, 11, 12, ... up to and including 20.
[3 marks]

Q13 Enter the output produced when you run the code you devised for
Q2. [2 marks]

THE DEL STATEMENT

There is a way to remove an item from a list given its index instead of its value: the del
statement. This differs from the pop()) method which returns a value. The del statement
can also be used to remove slices from a list or clear the entire list (which we did earlier by
assignment of an empty list to the slice). For example:

>>> a = [-1, 1, 66.25, 333, 333, 1234.5]

>>> del a[0]

>>> a

[1, 66.25, 333, 333, 1234.5]

>>> del a[2:4]

>>> a

[1, 66.25, 1234.5]

>>> del a[:]

>>> a

[]

del can also be used to delete entire variables:

>>> del a

Referencing the name a hereafter is an error (at least until another value is assigned to it).

School of Computer Science and Elec. Eng,, Bangor University 16 2022 / 2023
ICE-4101 – Introduction to Programming Semester 1 - Laboratory 2

EXERCISE 2.3 – DELETION FROM A LIST (7 MARKS)

This exercise will explore using the del command to delete from a list. In the Python
command line, first set the list a as follows:

>>> a=[2,4,6,8,10,12,14,16,18,20,22,24,26,28,30]

Write the code that will delete the current items in this list that are at the prime index
locations e.g. at index 2, index 3 and so on. Do this using a single line of code. (Hint: You can
use the “;” character to separate multiple commands on the same line).

Q14 Enter the code you would type that will delete the current items
in list a that are at the prime index locations. [5 marks]

Q15 Enter the output produced when you run the code you devised for
Q14. [2 marks]

TUPLES AND SEQUENCES

We saw that lists and strings have many common properties, such as indexing and slicing
operations. They are two examples of sequence data types. Since Python is an evolving
language, other sequence data types may be added. There is also another standard
sequence data type: the tuple.

A tuple consists of a number of values separated by commas, for instance:

>>> t = 12345, 54321, 'hello!'

>>> t[0]

12345

>>> t

(12345, 54321, 'hello!')

>>> # Tuples may be nested:

... u = t, (1, 2, 3, 4, 5)

>>> u

((12345, 54321, 'hello!'), (1, 2, 3, 4, 5))

School of Computer Science and Elec. Eng,, Bangor University 17 2022 / 2023
ICE-4101 – Introduction to Programming Semester 1 - Laboratory 2

As you see, on output tuples are always enclosed in parentheses, so that nested tuples are
interpreted correctly; they may be input with or without surrounding parentheses, although
often parentheses are necessary anyway (if the tuple is part of a larger expression).

Tuples have many uses. For example: (x, y) coordinate pairs, employee records from a
database, etc. Tuples, like strings, are immutable: it is not possible to assign to the individual
items of a tuple (you can simulate much of the same effect with slicing and concatenation,
though). It is also possible to create tuples which contain mutable objects, such as lists.

A special problem is the construction of tuples containing 0 or 1 items: the syntax has some
extra quirks to accommodate these. Empty tuples are constructed by an empty pair of
parentheses; a tuple with one item is constructed by following a value with a comma (it is
not sufficient to enclose a single value in parentheses). Ugly, but effective. For example:

>>> empty = ()

>>> singleton = 'hello', # <-- note trailing comma

>>> len(empty)

>>> len(singleton)

>>> singleton

('hello',)

The statement t = 12345, 54321, 'hello!' is an example of tuple packing: the


values 12345, 54321 and 'hello!' are packed together in a tuple. The reverse
operation is also possible:

>>> x, y, z = t

This is called, appropriately enough, sequence unpacking. Sequence unpacking requires


the list of variables on the left to have the same number of elements as the length of the
sequence. Note that multiple assignment is really just a combination of tuple packing and
sequence unpacking!

There is a small bit of asymmetry here: packing multiple values always creates a tuple, and
unpacking works for any sequence.

School of Computer Science and Elec. Eng,, Bangor University 18 2022 / 2023
ICE-4101 – Introduction to Programming Semester 1 - Laboratory 2

EXERCISE 2.4 – THE NEXT PRESIDENT (14 MARKS)

The purpose of this exercise is to write some code in Python to store the name of a person,
their age, their address and their occupation in a tuple. E.g.

Name: Donald Trump

Age: 70

Address: The White House, Pensylvania Avenue, Washington D.C., U.S.A.

Occupation: President of the good ol' U.S.A.

Q16 Enter the code you would type that stores the above information
as strings or numbers (in the same order exactly as above) in a
single tuple called president using a single line of code.
[4 marks; note – do not include the “Name:” and “Age:” etc. parts.]

Q17 Enter the code for unpacking the information you have stored in
the tuple you devised for Q16 into separate variables called name,
age, address and occupation. [4 marks]

Q18 Enter the code for repacking the information into a new variable
called president_in_2021 but also make sure you add 4 to the age
variable as you repack the information. [4 marks]

Q19 Enter the value of the variable president_in_2021. [2 marks]

SETS

Python also includes a data type for sets. A set is an unordered collection with no duplicate
elements. Basic uses include membership testing and eliminating duplicate entries. Set
objects also support mathematical operations like union, intersection, difference, and
symmetric difference.

Here is a brief demonstration:

School of Computer Science and Elec. Eng,, Bangor University 19 2022 / 2023
ICE-4101 – Introduction to Programming Semester 1 - Laboratory 2

>>> basket = ['apple', 'orange', 'apple', 'pear', 'orange',


'banana']

>>> fruit = set(basket) # create a set without


duplicates

>>> fruit

set(['orange', 'pear', 'apple', 'banana'])

>>> 'orange' in fruit # fast membership


testing

True

>>> 'crabgrass' in fruit

False

>>> # Demonstrate set operations on unique letters from two


words

...

>>> a = set('abracadabra')

>>> b = set('alacazam')

>>> a # unique letters in a

set(['a', 'r', 'b', 'c', 'd'])

>>> a - b # letters in a but not


in b

set(['r', 'd', 'b'])

>>> a | b # letters in either a


or b

set(['a', 'c', 'r', 'd', 'b', 'm', 'z', 'l'])

>>> a & b # letters in both a and


b

set(['a', 'c'])

>>> a ^ b # letters in a or b but


not both
School of Computer Science and Elec. Eng,, Bangor University 20 2022 / 2023
ICE-4101 – Introduction to Programming Semester 1 - Laboratory 2

set(['r', 'd', 'b', 'm', 'z', 'l'])

DICTIONARIES

Another useful data type built into Python is the dictionary. Dictionaries are sometimes
found in other languages as ``associative memories'' or ``associative arrays''. Unlike
sequences, which are indexed by a range of numbers, dictionaries are indexed by keys,
which can be any immutable type; strings and numbers can always be keys. Tuples can be
used as keys if they contain only strings, numbers, or tuples; if a tuple contains any mutable
object either directly or indirectly, it cannot be used as a key. You can't use lists as keys,
since lists can be modified in place using index assignments, slice assignments, or methods
like append() and extend().

It is best to think of a dictionary as an unordered set of key: value pairs, with the
requirement that the keys are unique (within one dictionary). A pair of braces creates an
empty dictionary: {}. Placing a comma-separated list of key:value pairs within the braces
adds initial key:value pairs to the dictionary; this is also the way dictionaries are written on
output.

The main operations on a dictionary are storing a value with some key and extracting the
value given the key. It is also possible to delete a key:value pair with del. If you store using
a key that is already in use, the old value associated with that key is forgotten. It is an error
to extract a value using a non-existent key.

The keys() method of a dictionary object returns a list of all the keys used in the
dictionary, in arbitrary order (if you want it sorted, just apply the sort() method to the list
of keys). To check whether a single key is in the dictionary, either use the dictionary's
has_key() method or the in keyword.

Here is a small example using a dictionary:

>>> tel = {'jack': 4098, 'sape': 4139}

>>> tel['guido'] = 4127

>>> tel

{'sape': 4139, 'guido': 4127, 'jack': 4098}

>>> tel['jack']

4098

>>> del tel['sape']


School of Computer Science and Elec. Eng,, Bangor University 21 2022 / 2023
ICE-4101 – Introduction to Programming Semester 1 - Laboratory 2

>>> tel['irv'] = 4127

>>> tel

{'guido': 4127, 'irv': 4127, 'jack': 4098}

>>> tel.keys()

['guido', 'irv', 'jack']

>>> tel.has_key('guido')

True

>>> 'guido' in tel

True

When the keys are simple strings, it is sometimes easier to specify pairs using keyword
arguments:

>>> dict(sape=4139, guido=4127, jack=4098)

{'sape': 4139, 'jack': 4098, 'guido': 4127}

EXERCISE 2.5 – THE SET DATA STRUCTURE (11 MARKS)

We will now do some exercises to learn more about the set and dictionary data structures.
We can use these data structures to store information in order to represent knowledge
(when building a knowledge based system or an intelligent system).

The first ‘set’ of exercises here concerns the ‘set’ data structure.

[2 marks for each of the following questions]

Q20 Enter code that will assign to the variable a the set of letters
in the following string:

'Now is the time for all good men to come to the aid of their party.'

Q21 Enter code that will assign to the variable b the set of letters
in the following string:

School of Computer Science and Elec. Eng,, Bangor University 22 2022 / 2023
ICE-4101 – Introduction to Programming Semester 1 - Laboratory 2

'We hold these truths to be self-evident, that all men are created equal, that they are
endowed by their Creator with certain unalienable Rights, that among these are Life, Liberty
and the pursuit of Happiness.'

[1 mark for each of the following questions]

Q22 Enter Python output that lists the letters in set b but not in
set a.

Q23 Enter Python output that lists the unique letters in set b.

Q24 Enter Python output that lists the letters in either set a or
set b but not both.

Q25 Enter Python output that lists the letters in either set a or
set b.

Q26 Enter Python output that lists the unique letters in set a.

Q27 Enter Python output that lists the letters in set a but not in
set b.

Q28 Enter Python output that lists the letters in both set a and set
b.

School of Computer Science and Elec. Eng,, Bangor University 23 2022 / 2023
ICE-4101 – Introduction to Programming Semester 1 - Laboratory 2

LOOPING TECHNIQUES

When looping through dictionaries, the key and corresponding value can be retrieved at the
same time using the items() method.

>>> knights = {'gallahad': 'the pure', 'robin': 'the brave'}

>>> for k, v in knights.items():

... print (k, v)

...

gallahad the pure

robin the brave

When looping through a sequence, the position index and corresponding value can be
retrieved at the same time using the enumerate() function.

>>> for i, v in enumerate(['tic', 'tac', 'toe']):

... print (i, v)

...

0 tic

1 tac

2 toe

To loop over two or more sequences at the same time, the entries can be paired with the
zip() function.

>>> questions = ['name', 'quest', 'favorite color']

>>> answers = ['lancelot', 'the holy grail', 'blue']

>>> for q, a in zip(questions, answers):

... print ('What is your %s? It is %s.' % (q, a))

...

What is your name? It is lancelot.

School of Computer Science and Elec. Eng,, Bangor University 24 2022 / 2023
ICE-4101 – Introduction to Programming Semester 1 - Laboratory 2

What is your quest? It is the holy grail.

What is your favorite color? It is blue.

To loop over a sequence in reverse, first specify the sequence in a forward direction and
then call the reversed() function.

>>> for i in reversed(xrange(1,10,2)):

... print (i)

...

To loop over a sequence in sorted order, use the sorted() function which returns a new
sorted list while leaving the source unaltered.

>>> basket = ['apple', 'orange', 'apple', 'pear', 'orange',


'banana']

>>> for f in sorted(set(basket)):

... print (f)

...

apple

banana

orange

pear

EXERCISE 2.6 – AMERICAN PRESIDENTS – PAST AND PRESENT – AND THE DICTIONARY
DATA STRUCTURE (24 MARKS)

School of Computer Science and Elec. Eng,, Bangor University 25 2022 / 2023
ICE-4101 – Introduction to Programming Semester 1 - Laboratory 2

In this exercise, we will create dictionaries to store facts about the following American
Presidents (e.g. their name and when they started in office):

Donald Trump 2017


Barack Obama 2009
George W. Bush 2001
Bill Clinton 1993
George Bush 1989

First of all, we need to create variables for each of the five presidential dictionaries.

Q29 Enter a single line of code that will assign an empty dictionary
to each of the five variables – donald, barack, george_w, bill
and george. [3 marks]
[Make sure you create the variables in the order shown, and do not include spaces in your
answer. Also use commas in your code instead of semi-colons.]

Q30 Enter a single line of code that will set the correct name
strings (as listed above) as values to the ‘Name’ key for each
of the five dictionaries. [3 marks]
[Make sure you set the variables in the order shown, and do not include spaces in your
answer. You will need to use semi-colons this-time.]

Q31 Enter a single line of code that will set the correct years (as
listed above) as values to the ‘Year’ key for each of the five
dictionaries. [3 marks]
[Make sure you set the variables in the order shown, and do not include spaces in your
answer. You will need to use semi-colons again this-time.]

Q32 Enter a single line of code that will iterate over the donald
dictionary and print out the keys and values within it.[3 marks]

Q33 Enter the output that is produced when you do the same for the
george dictionary. [2 marks]

Q34 Enter a single line of code that will create a tuple in a variable
called presidents that will contain the five dictionaries
(donald, barack, george_w, bill and george). [3 marks]

Q35 Enter the output that is produced when you print out the value
of the presidents variable. [2 marks]

Q36 Enter a single line of code that will instead create an array in
a variable called presidents1 that will contain the five
dictionaries (donald, barack, george_w, bill and george) at
index locations 0, 1, 2, 3 and 4 respectively. [3 marks]
School of Computer Science and Elec. Eng,, Bangor University 26 2022 / 2023
ICE-4101 – Introduction to Programming Semester 1 - Laboratory 2

Q37 Enter the output that is produced when you print out the value
of the presidents1 variable. [2 marks]

Note: Make sure you keep the value of the variable presidents1 loaded in Python as
you will need to have it for Exercise 2.7 below.

MORE ON CONDITIONS

The conditions used in while and if statements can contain any operators, not just
comparisons.

The comparison operators in and not in check whether a value occurs (does not occur)
in a sequence. The operators is and is not compare whether two objects are really the
same object; this only matters for mutable objects like lists. All comparison operators have
the same priority, which is lower than that of all numerical operators.

Comparisons can be chained. For example, a < b == c tests whether a is less than b and
moreover b equals c.

Comparisons may be combined using the Boolean operators and and or, and the outcome
of a comparison (or of any other Boolean expression) may be negated with not. These have
lower priorities than comparison operators; between them, not has the highest priority and
or the lowest, so that A and not B or C is equivalent to (A and (not B)) or C.
As always, parentheses can be used to express the desired composition.

The Boolean operators and and or are so-called short-circuit operators: their arguments
are evaluated from left to right, and evaluation stops as soon as the outcome is determined.
For example, if A and C are true but B is false, A and B and C does not evaluate the
expression C. When used as a general value and not as a Boolean, the return value of a
short-circuit operator is the last evaluated argument.

It is possible to assign the result of a comparison or other Boolean expression to a variable.


For example,

>>> string1, string2, string3 = '', 'Trondheim', 'Hammer


Dance'

>>> non_null = string1 or string2 or string3

>>> non_null
School of Computer Science and Elec. Eng,, Bangor University 27 2022 / 2023
ICE-4101 – Introduction to Programming Semester 1 - Laboratory 2

'Trondheim'

Note that in Python, unlike C, assignment cannot occur inside expressions. C programmers
may grumble about this, but it avoids a common class of problems encountered in C
programs: typing = in an expression when == was intended.

COMPARING SEQUENCES AND OTHER TYPES

Sequence objects may be compared to other objects with the same sequence type. The
comparison uses lexicographical ordering: first the first two items are compared, and if
they differ this determines the outcome of the comparison; if they are equal, the next two
items are compared, and so on, until either sequence is exhausted. If two items to be
compared are themselves sequences of the same type, the lexicographical comparison is
carried out recursively. If all items of two sequences compare equal, the sequences are
considered equal. If one sequence is an initial sub-sequence of the other, the shorter
sequence is the smaller (lesser) one. Lexicographical ordering for strings uses the ASCII
ordering for individual characters. Some examples of comparisons between sequences of the
same type:

(1, 2, 3) < (1, 2, 4)

[1, 2, 3] < [1, 2, 4]

'ABC' < 'C' < 'Pascal' < 'Python'

(1, 2, 3, 4) < (1, 2, 4)

(1, 2) < (1, 2, -1)

(1, 2, 3) == (1.0, 2.0, 3.0)

(1, 2, ('aa', 'ab')) < (1, 2, ('abc', 'a'), 4)

Note that comparing objects of different types is legal. The outcome is deterministic but
arbitrary: the types are ordered by their name. Thus, a list is always smaller than a string, a
string is always smaller than a tuple, etc. Mixed numeric types are compared according to
their numeric value, so 0 equals 0.0, etc.

MODULES

School of Computer Science and Elec. Eng,, Bangor University 28 2022 / 2023
ICE-4101 – Introduction to Programming Semester 1 - Laboratory 2

If you quit from the Python interpreter and enter it again, the definitions you have made
(functions and variables) are lost. Therefore, if you want to write a somewhat longer
program, you are better off using a text editor to prepare the input for the interpreter and
running it with that file as input instead. This is known as creating a script. As your program
gets longer, you may want to split it into several files for easier maintenance. You may also
want to use a handy function that you've written in several programs without copying its
definition into each program.

To support this, Python has a way to put definitions in a file and use them in a script or in an
interactive instance of the interpreter. Such a file is called a module; definitions from a
module can be imported into other modules or into the main module (the collection of
variables that you have access to in a script executed at the top level and in calculator
mode).

A module is a file containing Python definitions and statements. The file name is the module
name with the suffix .py appended. Within a module, the module's name (as a string) is
available as the value of the global variable __name__. For instance, use your favorite text
editor to create a file called fibo.py in the current directory with the following contents:

# Fibonacci numbers module

def fib(n): # write Fibonacci series up to n

a, b = 0, 1

while b < n:

print (b, end = '')

a, b = b, a+b

def fib2(n): # return Fibonacci series up to n

result = []

a, b = 0, 1

while b < n:

result.append(b)

a, b = b, a+b

return result

School of Computer Science and Elec. Eng,, Bangor University 29 2022 / 2023
ICE-4101 – Introduction to Programming Semester 1 - Laboratory 2

Now enter the Python interpreter and import this module with the following command:

>>> import fibo

This does not enter the names of the functions defined in fibo directly in the current symbol
table; it only enters the module name fibo there. Using the module name you can access
the functions:

>>> fibo.fib(1000)

1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987

>>> fibo.fib2(100)

[1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]

>>> fibo.__name__

'fibo'

If you intend to use a function often you can assign it to a local name:

>>> fib = fibo.fib

>>> fib(500)

1 1 2 3 5 8 13 21 34 55 89 144 233 377

MORE ON MODULES

A module can contain executable statements as well as function definitions. These


statements are intended to initialize the module. They are executed only the first time the
module is imported somewhere.

Each module has its own private symbol table, which is used as the global symbol table by all
functions defined in the module. Thus, the author of a module can use global variables in the
module without worrying about accidental clashes with a user's global variables. On the
other hand, if you know what you are doing you can touch a module's global variables with
the same notation used to refer to its functions, modname.itemname.

Modules can import other modules. It is customary but not required to place all import
statements at the beginning of a module (or script, for that matter). The imported module
names are placed in the importing module's global symbol table.

School of Computer Science and Elec. Eng,, Bangor University 30 2022 / 2023
ICE-4101 – Introduction to Programming Semester 1 - Laboratory 2

There is a variant of the import statement that imports names from a module directly into
the importing module's symbol table. For example:

>>> from fibo import fib, fib2

>>> fib(500)

1 1 2 3 5 8 13 21 34 55 89 144 233 377

This does not introduce the module name from which the imports are taken in the local
symbol table (so in the example, fibo is not defined).

There is even a variant to import all names that a module defines:

>>> from fibo import *

>>> fib(500)

1 1 2 3 5 8 13 21 34 55 89 144 233 377

This imports all names except those beginning with an underscore (_).

“COMPILED” P YTHON FILES

As an important speed-up of the start-up time for short programs that use a lot of standard
modules, if a file called spam.pyc exists in the directory where spam.py is found, this is
assumed to contain an already-``byte-compiled'' version of the module spam. The
modification time of the version of spam.py used to create spam.pyc is recorded in
spam.pyc, and the .pyc file is ignored if these don't match.

Normally, you don't need to do anything to create the spam.pyc file. Whenever spam.py is
successfully compiled, an attempt is made to write the compiled version to spam.pyc. It is
not an error if this attempt fails; if for any reason the file is not written completely, the
resulting spam.pyc file will be recognized as invalid and thus ignored later. The contents of
the spam.pyc file are platform independent, so a Python module directory can be shared by
machines of different architectures.

STANDARD MODULES

Python comes with a library of standard modules, described in a separate document, the
Python Library Reference (``Library Reference'' hereafter). Some modules are built into the
School of Computer Science and Elec. Eng,, Bangor University 31 2022 / 2023
ICE-4101 – Introduction to Programming Semester 1 - Laboratory 2

interpreter; these provide access to operations that are not part of the core of the language
but are nevertheless built in, either for efficiency or to provide access to operating system
primitives such as system calls. The set of such modules is a configuration option which also
depends on the underlying platform For example, the amoeba module is only provided on
systems that somehow support Amoeba primitives. One particular module deserves some
attention: sys, which is built into every Python interpreter. The variables sys.ps1 and
sys.ps2 define the strings used as primary and secondary prompts:

>>> import sys

>>> sys.ps1

'>>> '

>>> sys.ps2

'... '

>>> sys.ps1 = 'C> '

C> print ('Yuck!')

Yuck!

C>

These two variables are only defined if the interpreter is in interactive mode.

THE DIR() FUNCTION

The built-in function dir() is used to find out which names a module defines. It returns a
sorted list of strings:

>>> import fibo, sys

>>> dir(fibo)

['__name__', 'fib', 'fib2']

>>> dir(sys)

['__displayhook__', '__doc__', '__excepthook__', '__name__',


'__stderr__',

'__stdin__', '__stdout__', '_getframe', 'api_version',


'argv',
School of Computer Science and Elec. Eng,, Bangor University 32 2022 / 2023
ICE-4101 – Introduction to Programming Semester 1 - Laboratory 2

'builtin_module_names', 'byteorder', 'callstats',


'copyright',

'displayhook', 'exc_clear', 'exc_info', 'exc_type',


'excepthook',

'exec_prefix', 'executable', 'exit', 'getdefaultencoding',


'getdlopenflags',

'getrecursionlimit', 'getrefcount', 'hexversion', 'maxint',


'maxunicode',

'meta_path', 'modules', 'path', 'path_hooks',


'path_importer_cache',

'platform', 'prefix', 'ps1', 'ps2', 'setcheckinterval',


'setdlopenflags',

'setprofile', 'setrecursionlimit', 'settrace', 'stderr',


'stdin', 'stdout',

'version', 'version_info', 'warnoptions']

Without arguments, dir() lists the names you have defined currently:

>>> a = [1, 2, 3, 4, 5]

>>> import fibo

>>> fib = fibo.fib

>>> dir()

['__builtins__', '__doc__', '__file__', '__name__', 'a',


'fib', 'fibo', 'sys']

Note that it lists all types of names: variables, modules, functions, etc.

dir() does not list the names of built-in functions and variables. If you want a list of those,
they are defined in the standard module __builtin__:

>>> import __builtin__

>>> dir(__builtin__)

['ArithmeticError', 'AssertionError', 'AttributeError',


'DeprecationWarning',

School of Computer Science and Elec. Eng,, Bangor University 33 2022 / 2023
ICE-4101 – Introduction to Programming Semester 1 - Laboratory 2

'EOFError', 'Ellipsis', 'EnvironmentError', 'Exception',


'False',

'FloatingPointError', 'FutureWarning', 'IOError',


'ImportError',

'IndentationError', 'IndexError', 'KeyError',


'KeyboardInterrupt',

'LookupError', 'MemoryError', 'NameError', 'None',


'NotImplemented',

'NotImplementedError', 'OSError', 'OverflowError',

'PendingDeprecationWarning', 'ReferenceError',
'RuntimeError',

'RuntimeWarning', 'StandardError', 'StopIteration',


'SyntaxError',

'SyntaxWarning', 'SystemError', 'SystemExit', 'TabError',


'True',

'TypeError', 'UnboundLocalError', 'UnicodeDecodeError',

'UnicodeEncodeError', 'UnicodeError',
'UnicodeTranslateError',

'UserWarning', 'ValueError', 'Warning', 'WindowsError',

'ZeroDivisionError', '_', '__debug__', '__doc__',


'__import__',

'__name__', 'abs', 'apply', 'basestring', 'bool', 'buffer',

'callable', 'chr', 'classmethod', 'cmp', 'coerce', 'compile',

'complex', 'copyright', 'credits', 'delattr', 'dict', 'dir',


'divmod',

'enumerate', 'eval', 'execfile', 'exit', 'file', 'filter',


'float',

'frozenset', 'getattr', 'globals', 'hasattr', 'hash', 'help',


'hex',

'id', 'input', 'int', 'intern', 'isinstance', 'issubclass',


'iter',

School of Computer Science and Elec. Eng,, Bangor University 34 2022 / 2023
ICE-4101 – Introduction to Programming Semester 1 - Laboratory 2

'len', 'license', 'list', 'locals', 'long', 'map', 'max',


'min',

'object', 'oct', 'open', 'ord', 'pow', 'property', 'quit',


'range',

'reduce', 'reload', 'repr', 'reversed', 'round', 'set',

'setattr', 'slice', 'sorted', 'staticmethod', 'str', 'sum',


'super',

'tuple', 'type', 'unichr', 'unicode', 'vars', 'xrange',


'zip']

PACKAGES

Packages are a way of structuring Python's module namespace by using ``dotted module
names''. For example, the module name A.B designates a submodule named "B" in a
package named "A". Just like the use of modules saves the authors of different modules
from having to worry about each other's global variable names, the use of dotted module
names saves the authors of multi-module packages like NumPy or the Python Imaging
Library from having to worry about each other's module names.

Suppose you want to design a collection of modules (a “package”) for the uniform handling
of sound files and sound data. There are many different sound file formats (usually
recognized by their extension, for example: .wav, .aiff, .au), so you may need to create and
maintain a growing collection of modules for the conversion between the various file
formats. There are also many different operations you might want to perform on sound data
(such as mixing, adding echo, applying an equalizer function, creating an artificial stereo
effect), so in addition you will be writing a never-ending stream of modules to perform these
operations. Here's a possible structure for your package (expressed in terms of a hierarchical
filesystem):

Sound/ Top-level package

__init__.py Initialize the sound package

Formats/ Subpackage for file format


conversions

__init__.py

School of Computer Science and Elec. Eng,, Bangor University 35 2022 / 2023
ICE-4101 – Introduction to Programming Semester 1 - Laboratory 2

wavread.py

wavwrite.py

aiffread.py

aiffwrite.py

auread.py

auwrite.py

...

Effects/ Subpackage for sound effects

__init__.py

echo.py

surround.py

reverse.py

...

Filters/ Subpackage for filters

__init__.py

equalizer.py

vocoder.py

karaoke.py

...

Users of the package can import individual modules from the package, for example:

import Sound.Effects.echo

This loads the submodule Sound.Effects.echo. It must be referenced with its full
name.

Sound.Effects.echo.echofilter(input, output, delay=0.7,


atten=4)

An alternative way of importing the submodule is:

School of Computer Science and Elec. Eng,, Bangor University 36 2022 / 2023
ICE-4101 – Introduction to Programming Semester 1 - Laboratory 2

from Sound.Effects import echo

This also loads the submodule echo, and makes it available without its package prefix, so it
can be used as follows:

echo.echofilter(input, output, delay=0.7, atten=4)

Yet another variation is to import the desired function or variable directly:

from Sound.Effects.echo import echofilter

Again, this loads the submodule echo, but this makes its function echofilter() directly
available:

echofilter(input, output, delay=0.7, atten=4)

Note that when using from package import item, the item can be either a submodule
(or subpackage) of the package, or some other name defined in the package, like a function,
class or variable. The import statement first tests whether the item is defined in the
package; if not, it assumes it is a module and attempts to load it. If it fails to find it, an
ImportError exception is raised.

Contrarily, when using syntax like import item.subitem.subsubitem, each item except for
the last must be a package; the last item can be a module or a package but can't be a class or
function or variable defined in the previous item.

Some further examples of the Import command:

import Sound.Effects.echo

import Sound.Effects.surround

from Sound.Effects import *

Note that in general the practice of importing * from a module or package is frowned upon,
since it often causes poorly readable code. However, it is okay to use it to save typing in
interactive sessions, and certain modules are designed to export only names that follow
certain patterns.

Remember, there is nothing wrong with using from Package import


specific_submodule! In fact, this is the recommended notation unless the importing
module needs to use submodules with the same name from different packages.

School of Computer Science and Elec. Eng,, Bangor University 37 2022 / 2023
ICE-4101 – Introduction to Programming Semester 1 - Laboratory 2

INPUT AND OUTPUT

There are several ways to present the output of a program; data can be printed in a human-
readable form, or written to a file for future use. This chapter will discuss some of the
possibilities.

FANCIER OUTPUT FORMATTING

So far we've encountered two ways of writing values: expression statements and the
print statement. (A third way is using the write() method of file objects; the standard
output file can be referenced as sys.stdout. See the Library Reference for more
information on this.)

Often you'll want more control over the formatting of your output than simply printing
space-separated values. There are two ways to format your output; the first way is to do all
the string handling yourself; using string slicing and concatenation operations you can create
any layout you can imagine. The standard module string contains some useful operations
for padding strings to a given column width; these will be discussed shortly. The second way
is to use the % operator with a string as the left argument. The % operator interprets the left
argument much like a sprintf()-style format string to be applied to the right argument,
and returns the string resulting from this formatting operation.

One question remains, of course: how do you convert values to strings? Luckily, Python has
ways to convert any value to a string: pass it to the repr() or str() functions. Reverse
quotes (``) are equivalent to repr(), but they are no longer used in modern Python code and
will likely not be in future versions of the language.

The str() function is meant to return representations of values which are fairly human-
readable, while repr() is meant to generate representations which can be read by the
interpreter (or will force a SyntaxError if there is not equivalent syntax). For objects
which don't have a particular representation for human consumption, str() will return the
same value as repr(). Many values, such as numbers or structures like lists and
dictionaries, have the same representation using either function. Strings and floating point
numbers, in particular, have two distinct representations.

Some examples:

>>> s = 'Hello, world.'

>>> str(s)
School of Computer Science and Elec. Eng,, Bangor University 38 2022 / 2023
ICE-4101 – Introduction to Programming Semester 1 - Laboratory 2

'Hello, world.'

>>> repr(s)

"'Hello, world.'"

>>> str(0.1)

'0.1'

>>> repr(0.1)

'0.1'

>>> x = 10 * 3.25

>>> y = 200 * 200

>>> s = 'The value of x is ' + repr(x) + ', and y is ' +


repr(y) + '...'

>>> print (s)

The value of x is 32.5, and y is 40000...

>>> # The repr() of a string adds string quotes and


backslashes:

... hello = 'hello, world\n'

>>> hellos = repr(hello)

>>> print (hellos)

'hello, world\n'

>>> # The argument to repr() may be any Python object:

... repr((x, y, ('spam', 'eggs')))

"(32.5, 40000, ('spam', 'eggs'))"

>>> # reverse quotes are convenient in interactive sessions:

... `x, y, ('spam', 'eggs')`

"(32.5, 40000, ('spam', 'eggs'))"

Here are two ways to write a table of squares and cubes:

>>> for x in range(1, 11):

School of Computer Science and Elec. Eng,, Bangor University 39 2022 / 2023
ICE-4101 – Introduction to Programming Semester 1 - Laboratory 2

... print (repr(x).rjust(2), repr(x*x).rjust(3), end = '')

... # Note trailing comma on previous line

... print (repr(x*x*x).rjust(5))

...

1 1 1

2 4 8

3 9 27

4 16 64

5 25 125

6 36 216

7 49 343

8 64 512

9 81 729

10 100 1000

>>> for x in range(1,11):

... print ('%2d %3d %4d' % (x, x*x, x*x*x))

...

1 1 1

2 4 8

3 9 27

4 16 64

5 25 125

6 36 216

7 49 343

8 64 512

9 81 729

10 100 1000
School of Computer Science and Elec. Eng,, Bangor University 40 2022 / 2023
ICE-4101 – Introduction to Programming Semester 1 - Laboratory 2

(Note that one space between each column was added by the way print works: it always
adds spaces between its arguments.)

This example demonstrates the rjust() method of string objects, which right-justifies a
string in a field of a given width by padding it with spaces on the left. There are similar
methods ljust() and center(). These methods do not write anything, they just return
a new string. If the input string is too long, they don't truncate it, but return it unchanged;
this will mess up your column lay-out but that's usually better than the alternative, which
would be lying about a value. (If you really want truncation you can always add a slice
operation, as in "x.ljust(n)[:n]".)

There is another method, zfill(), which pads a numeric string on the left with zeros. It
understands about plus and minus signs:

>>> '12'.zfill(5)

'00012'

>>> '-3.14'.zfill(7)

'-003.14'

>>> '3.14159265359'.zfill(5)

'3.14159265359'

Using the % operator looks like this:

>>> import math

>>> print('The value of PI is approximately %5.3f.' % math.pi)

The value of PI is approximately 3.142.

If there is more than one format in the string, you need to pass a tuple as right operand, as
in this example:

>>> table = {'Sjoerd': 4127, 'Jack': 4098, 'Dcab': 7678}

>>> for name, phone in table.items():

... print ('%-10s ==> %10d' % (name, phone))

...

Jack ==> 4098

School of Computer Science and Elec. Eng,, Bangor University 41 2022 / 2023
ICE-4101 – Introduction to Programming Semester 1 - Laboratory 2

Dcab ==> 7678

Sjoerd ==> 4127

Most formats work exactly as in C and require that you pass the proper type; however, if you
don't you get an exception, not a core dump. The %s format is more relaxed: if the
corresponding argument is not a string object, it is converted to string using the str()
built-in function. Using * to pass the width or precision in as a separate (integer) argument is
supported. The C formats %n and %p are not supported.

If you have a really long format string that you don't want to split up, it would be nice if you
could reference the variables to be formatted by name instead of by position. This can be
done by using form %(name)format, as shown here:

>>> table = {'Sjoerd': 4127, 'Jack': 4098, 'Dcab': 8637678}

>>> print ('Jack: %(Jack)d; Sjoerd: %(Sjoerd)d; Dcab:


%(Dcab)d' % table)

Jack: 4098; Sjoerd: 4127; Dcab: 8637678

This is particularly useful in combination with the new built-in vars() function, which
returns a dictionary containing all local variables.

READING AND WRITING FILES

open() returns a file object, and is most commonly used with two arguments:
"open(filename, mode)".

>>> f=open('/tmp/workfile', 'w')

>>> print (f)

<open file '/tmp/workfile', mode 'w' at 80a0960>

The first argument is a string containing the filename. The second argument is another string
containing a few characters describing the way in which the file will be used. mode can be
'r' when the file will only be read, 'w' for only writing (an existing file with the same
name will be erased), and 'a' opens the file for appending; any data written to the file is
automatically added to the end. 'r+' opens the file for both reading and writing. The mode
argument is optional; 'r' will be assumed if it's omitted.

School of Computer Science and Elec. Eng,, Bangor University 42 2022 / 2023
ICE-4101 – Introduction to Programming Semester 1 - Laboratory 2

On Windows and the Macintosh, 'b' appended to the mode opens the file in binary mode,
so there are also modes like 'rb', 'wb', and 'r+b'. Windows makes a distinction
between text and binary files; the end-of-line characters in text files are automatically
altered slightly when data is read or written. This behind-the-scenes modification to file data
is fine for ASCII text files, but it'll corrupt binary data like that in JPEG or EXE files. Be very
careful to use binary mode when reading and writing such files.

METHODS OF FILE OBJECTS

The rest of the examples in this section will assume that a file object called f has already
been created.

To read a file's contents, call f.read(size), which reads some quantity of data and returns
it as a string. size is an optional numeric argument. When size is omitted or negative, the
entire contents of the file will be read and returned; it's your problem if the file is twice as
large as your machine's memory. Otherwise, at most size bytes are read and returned. If the
end of the file has been reached, f.read() will return an empty string ("").

>>> f.read()

'This is the entire file.\n'

>>> f.read()

''

f.readline() reads a single line from the file; a newline character (\n) is left at the end
of the string, and is only omitted on the last line of the file if the file doesn't end in a
newline. This makes the return value unambiguous; if f.readline() returns an empty
string, the end of the file has been reached, while a blank line is represented by '\n', a
string containing only a single newline.

>>> f.readline()

'This is the first line of the file.\n'

>>> f.readline()

'Second line of the file\n'

>>> f.readline()

''

School of Computer Science and Elec. Eng,, Bangor University 43 2022 / 2023
ICE-4101 – Introduction to Programming Semester 1 - Laboratory 2

f.readlines() returns a list containing all the lines of data in the file. If given an
optional parameter sizehint, it reads that many bytes from the file and enough more to
complete a line, and returns the lines from that. This is often used to allow efficient reading
of a large file by lines, but without having to load the entire file in memory. Only complete
lines will be returned.

>>> f.readlines()

['This is the first line of the file.\n', 'Second line of the


file\n']

An alternate approach to reading lines is to loop over the file object. This is memory
efficient, fast, and leads to simpler code:

>>> for line in f:

print (line, end = '')

This is the first line of the file.

Second line of the file

The alternative approach is simpler but does not provide as fine-grained control. Since the
two approaches manage line buffering differently, they should not be mixed.

f.write(string) writes the contents of string to the file, returning None.

>>> f.write('This is a test\n')

To write something other than a string, it needs to be converted to a string first:

>>> value = ('the answer', 42)

>>> s = str(value)

>>> f.write(s)

f.tell() returns an integer giving the file object's current position in the file, measured in
bytes from the beginning of the file. To change the file object's position, use
"f.seek(offset, from_what)". The position is computed from adding offset to a reference
point; the reference point is selected by the from_what argument. A from_what value of 0
measures from the beginning of the file, 1 uses the current file position, and 2 uses the end

School of Computer Science and Elec. Eng,, Bangor University 44 2022 / 2023
ICE-4101 – Introduction to Programming Semester 1 - Laboratory 2

of the file as the reference point. from_what can be omitted and defaults to 0, using the
beginning of the file as the reference point.

>>> f = open('/tmp/workfile', 'r+')

>>> f.write('0123456789abcdef')

>>> f.seek(5) # Go to the 6th byte in the file

>>> f.read(1)

'5'

>>> f.seek(-3, 2) # Go to the 3rd byte before the end

>>> f.read(1)

'd'

When you're done with a file, call f.close() to close it and free up any system resources
taken up by the open file. After calling f.close(), attempts to use the file object will
automatically fail.

>>> f.close()

>>> f.read()

Traceback (most recent call last):

File "<stdin>", line 1, in ?

ValueError: I/O operation on closed file

File objects have some additional methods, such as isatty() and truncate() which
are less frequently used; consult the Library Reference for a complete guide to file objects.

THE PICKLE MODULE

Strings can easily be written to and read from a file. Numbers take a bit more effort, since
the read() method only returns strings, which will have to be passed to a function like
int(), which takes a string like '123' and returns its numeric value 123. However, when
you want to save more complex data types like lists, dictionaries, or class instances, things
get a lot more complicated.

School of Computer Science and Elec. Eng,, Bangor University 45 2022 / 2023
ICE-4101 – Introduction to Programming Semester 1 - Laboratory 2

Rather than have users be constantly writing and debugging code to save complicated data
types, Python provides a standard module called pickle. To get this module, you need to
import it first:

import pickle

This is an amazing module that can take almost any Python object (even some forms of
Python code!), and convert it to a string representation; this process is called pickling.
Reconstructing the object from the string representation is called unpickling. Between
pickling and unpickling, the string representing the object may have been stored in a file or
data, or sent over a network connection to some distant machine.

If you have an object x, and a file object f that's been opened for writing in binary mode, the
simplest way to pickle the object takes only two lines of code:

f = open ('/tmp/workfile', 'wb') # Open file in binary mode

pickle.dump(x, f)

To unpickle the object again, if f is a file object which has been opened for reading:

x = pickle.load(f)

pickle is the standard way to make Python objects which can be stored and reused by
other programs or by a future invocation of the same program; the technical term for this is
a persistent object. Because pickle is so widely used, many authors who write Python
extensions take care to ensure that new data types such as matrices can be properly pickled
and unpickled.

EXERCISE 2.7 – IN A PICKLE (15 MARKS)

In this exercise, you will pickle and unpickle the data structure you created in exercise 2.6.

Q38 Enter the code to open a new file called ‘presidents.pkl’


creating the file object f at the same time. [2.5 marks]

Q39 Enter code to dump the variable presidents1 that you assigned in
exercise 2.6 to the new file you just created. [3 marks]

Q40 Enter code to close the file called ‘presidents.pkl’. [2 marks]

School of Computer Science and Elec. Eng,, Bangor University 46 2022 / 2023
ICE-4101 – Introduction to Programming Semester 1 - Laboratory 2

Q41 Enter the code to again open the file you just created called
‘presidents.pkl’ using the file object f1 this time. [2.5 marks]

Q42 Enter the code to load the variable presidents2 from the pickled
data in the file pointed at by the file object f1. [3 marks]

Q43 Enter the code to close the file you used for questions Q41 and
Q42. [2 marks]

(Check that the value of the variable presidents2 is the same as the variable presidents1 to
verify that the unpickling has worked correctly).

School of Computer Science and Elec. Eng,, Bangor University 47 2022 / 2023

You might also like