Lab 02 - Functions, Lists, & File I/O
Due by 11:59pm on 2023-06-29.
Starter Files
Download lab02.zip. Inside the archive, you will find starter files for the questions in this lab.
Lists
A list is a data structure that can store multiple elements. Each element can be any type, even a list itself. We write a list as a comma-separated list of expressions in square brackets:
>>> list_of_ints = [1, 2, 3, 4]
>>> list_of_bools = [True, True, False, False]
>>> nested_lists = [1, [2, 3], [4, [5]]]
Each element in the list has an index, with the index of the first
element starting at 0. We say that lists are therefore “zero-indexed.”
With list indexing, we can specify the index of the element we want to
retrive. A negative index represents starting from the end of the list,
where the negative index -i is equivalent to the positive index
len(lst)-i.
>>> lst = [6, 5, 4, 3, 2, 1, 0]
>>> lst[0]
6
>>> lst[3]
3
>>> lst[-1] # Same as lst[6]
0
List slicing
To create a copy of part or all of a list, we can use list slicing. The
syntax to slice a list lst is:
lst[<start index>:<end index>:<step size>].
This expression evaluates to a new list containing the elements of
lst:
- Starting at and including the element at
<start index>. - Up to but not including the element at
<end index>. - With
<step size>as the difference between indices of elements to include.
If the start, end, or step size are not explicitly specified, Python has default values for them. A negative step size indicates that we are stepping backwards through a list when including elements.
>>> lst = [6, 5, 4, 3, 2, 1, 0]
>>> lst[:3] # Start index defaults to 0
[6, 5, 4]
>>> lst[3:] # End index defaults to len(lst)
[3, 2, 1, 0]
>>> lst[::-1] # Make a reversed copy of the entire list
[0, 1, 2, 3, 4, 5, 6]
>>> lst[::2] # Skip every other; step size defaults to 1 otherwise
[6, 4, 2, 0]
List comprehensions
List comprehensions are a compact and powerful way of creating new lists out of sequences. The general syntax for a list comprehension is the following:
[<expression> for <element> in <sequence> if <conditional>]
where the if <conditional> section is optional.
The syntax is designed to read like English: “Compute the expression for each element in the sequence (if the conditional is true for that element).”
>>> [i**2 for i in [1, 2, 3, 4] if i % 2 == 0]
[4, 16]
This list comprehension will:
- Compute the expression
i**2 - For each element
iin the sequence[1, 2, 3, 4] - Where
i % 2 == 0(iis an even number),
and then put the resulting values of the expressions into a new list.
In other words, this list comprehension will create a new list that
contains the square of every even element of the original list
[1, 2, 3, 4].
We can also rewrite a list comprehension as an equivalent for
statement, such as for the example above:
>>> lst = []
>>> for i in [1, 2, 3, 4]:
... if i % 2 == 0:
... lst = lst + [i**2]
>>> lst
[4, 16]
Both are completely valid, but the list comprehension is more compact and the more "Pythonic" way to do that operation. List comprehensions often seem odd when you first see them, but as you use them more, they become easier to understand and create.
Q1: WWPD: Lists
What would Python display for each of these?
>>> a = [1, 5, 4, [2, 3], 3]
>>> print(a[0], a[-1])
>>> len(a)
>>> 2 in a
>>> a[3][0]
Q2: Even weighted
Write a function that takes a list s and returns a new list that keeps
only the even-indexed elements of s and multiplies them by their
corresponding index.
def even_weighted(s):
"""
>>> x = [1, 2, 3, 4, 5, 6]
>>> even_weighted(x)
[0, 6, 20]
"""
return [_________________________________________________]
Q3: Couple
Implement the function couple(), which takes in two lists and returns a list that contains lists with i-th elements of two sequences coupled together. You can assume the lengths of two sequences are the same. Try using a list comprehension.
Hint: You may find the built in range function helpful.
def couple(s, t):
"""Return a list of two-element lists in which the i-th element is [s[i], t[i]].
>>> a = [1, 2, 3]
>>> b = [4, 5, 6]
>>> couple(a, b)
[[1, 4], [2, 5], [3, 6]]
>>> c = ['c', 6]
>>> d = ['s', '1']
>>> couple(c, d)
[['c', 's'], [6, '1']]
"""
assert len(s) == len(t)
"*** YOUR CODE HERE ***"
Q4: Factors List
Write factors_list, which takes a number n and returns a list of its
factors in ascending order.
def factors_list(n):
"""Return a list containing all the numbers that divide `n` evenly, except
for the number itself. Make sure the list is in ascending order.
>>> factors_list(6)
[1, 2, 3]
>>> factors_list(8)
[1, 2, 4]
>>> factors_list(28)
[1, 2, 4, 7, 14]
"""
all_factors = []
"*** YOUR CODE HERE ***"
Q5: Slice and Multiplice
Write a function slice-and-multiplice that takes in a list of integers called lst and returns a new list where all values past the first value are multiplied by the first value. In addition, the new list should not contain the first value.
Note: Make sure that you do not change the inputted list!
def slice_and_multiplice(lst):
"""Return a new list where all values past the first are
multiplied by the first value.
>>> slice_and_multiplice([1,1,6])
[1, 6]
>>> slice_and_multiplice([9,1,5,2])
[9, 45, 18]
>>> slice_and_multiplice([4])
[]
>>> slice_and_multiplice([0,4,9,18,20])
[0, 0, 0, 0]
"""
"*** YOUR CODE HERE ***"
File I/O
Whenever we shut down our electronic device, we lose information unless it is saved in a file. In this class, we will focus on writing to and reading from files.
Python already has a built-in way to create, write to, and read files.
To work with a file, we need to open it by using the open function and provide as arguments the filename and the mode we want to use. There are several different mode for opening a file such as write mode, read mode, or append mode.
Writing to a File
Since we want to write to the file, we use "w" for the mode. For example:
file = open("filename.txt", "w")
# filename mode
If the file does not exist and you are opening the file in write mode, then python will automatically create the file. If you do not provide a mode when opening a file, python will automatically open it in read mode.
To write content to the file, we use the write() method and provide the content we want to write as an argument. For example, building upon the previous code:
file.write("Hello World")
file.write(":D")
Right now, our file looks like this
Hello World:D
By default, the write() method does not put a new line; we have to do that ourselves by putting "\n" at the end of the string.
file.write("Hello World\n")
file.write(":D")
Additionally, we can use the writelines() method which takes in a list of strings and writes each of them into the file:
lines = ["Hello World\n", ":D"]
file.writelines(lines)
When you are finished working with the files, remember to close the file. It frees up space used when opening that file. To do that, we can do
file.close()
Reading From a File
There are multiple ways to read from a file. The following are a few methods to do so:
read()- returns a string containing all the contents of the file.readline()- returns a string with the contents of the first line. Once it returns the contents of the first line, another call toreadline()will return the contents of the second line, and so on and so forth until the final line.readlines()- returns a list of strings where each string is a line.
Note: When reading from a file, python will interpret new lines as a literal
"\n".
Remember, since these are methods, these follow the format of file.read(). The differences between methods and functions will become more apparent in lecture 8.
Q6: Copy File
Write copy_file, which takes two strings, input and output file names. It opens the two files, reads the input line by line and creates a string with the line number and a colon prepended to the line. It then prints the new string and writes it to the output file.
def copy_file(input, output):
"""Print each line from input with the line number and a colon prepended,
then write that line to the output file.
>>> copy_file('text.txt', 'output.txt')
1: They say you should never eat dirt.
2: It's not nearly as good as an onion.
3: It's not as good as the CS pun on my shirt.
"""
"*** YOUR CODE HERE ***"
Hint: When reading from a file, python will interpret the new lines as a literal
"\n". As a result, when printing a line, you will have an extra empty new line. To mitigate this, you can use useprint(line, end=""). By default,end="\n"and removing that allows to remove the extra empty new lines. There are also other solutions.
Submit
If you are not in lab today, submit your lab02.py file to Gradescope to receive credit.
Submissions will be in Canvas.
Otherwise, thanks for coming to lab! You don't have to submit anything.
Additional Info About FileIO:
Python supports another feature to open and close files.
We can rewrite this
file = open("filename.txt", "w")
file.write("Hello World")
file.close()
to this
with open("filename.txt", "w") as file
file.write("Hello World")
All the code that is indented after the with open, will have access to the file for writing.
Once python is finished executing the indented code, then the file automatically closes.