Lecture 9

Review

  1. What does each of the following produce?
    1. items = ['ant', 'bird', 'cat', 'dog']
      items[-2:]
    2. 'Newlines are represented with '\n' and show up as '
      ', i.e. a break in the line.'.split()
    3. 'Cats and dogs'.split('')
    4. ''.join(['Cats', 'and', 'dogs']
  2. Given a list called wishlist, how would you remove 'pony' from the list?
  3. How can we rewrite the if-statement below to be shorter and easier to read by using some of the common list operations from last class? value = input("Enter text: ")
    count = 0 #number of vowels in value
    for letter in value:
        if letter == 'a' or letter == 'e' or letter == 'i' or letter == 'o' or letter == 'u':
            count += 1

    print("There are", count, "lowercase vowels in the text you entered.")
  4. What does this code do: pet_names = 'Max,Buster,Molly,Sadie,Bandit,Milo,Lassie'
    short_pet_names = ','.join([n for n in pet_names.split(',') if len(n) <= 4])
  5. Rewrite the following code snippets to make use of list comprehension and some of the common list operations from last class

Lists and Tuples (concluded)

The list Function

There are times where you will want to convert something into a list. We haven't seen a lot of data structures yet, but a lot of them can be converted into a list using the list "function" (technically, it's a callable class, but it's most often used as a function). The list function takes any iterable object. Iterable objects are objects that we can do this to:

for val in iterable_object:
    #do something

So far, we've see these iterable objects:

When we use the range function, we get back a range object. Sometimes we want an actual list of the integers represented by the range. The example below shows how to convert a range object into a list.

>>> zero_thru_ten = range(11)
>>> print(type(zero_thru_ten))
range
>>> print(zero_thru_ten)
range(0, 11)
>>>
>>> zero_thru_ten = list(zero_thru_ten)
>>> print(type(zero_thru_ten))
list
>>> print(zero_thru_ten)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

Tuples

Tuples are almost like lists, except they can't change their values. So once a tuple is created, you cannot add new elements to it nor can you change the value of existing elements. To create a tuple:

You can also convert an iterable type into a tuple using the tuple "function":

>>> numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
>>> unchangeable = tuple(numbers)
>>> print(unchangeable)
(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
>>> print(type(unchangeable))
tuple

What's the point of tuples? Why have a list-like data type that can't change its values? It can be more efficient than lists because it doesn't need to be resized (lists actually allocate more memory than they're currently using to make insertions/appending faster).

Files

So far, all input to our programs have been through the keyboard and all output has been to the screen. This means that every time the user runs our programs, they must enter all of the data again. If there's a lot of data, this can take a long time. Additionally, if there's a lot of output, the user may be overwhelmed if it is all displayed on the screen. The solution to these problems is files.

There are different kinds of files, but two basic categories: text files and binary files. We will work with text files (binary files include sound files, picture files, zip files, and video files). There are two basic operations we can do with a file: read from a file or write to a file. We can only do one operation at a time (technically, that's not true, but things get more complicated if we try to do both). When we open a file, we must specify whether it is to read from or write to.

Writing to a file

To write to a file, we must first open it. To open it, we use the open function:

file_reference = open(file_location_and_name, 'w')

where:

With our file open, we can start writing to it. We write to it through our file_reference, using the write method. You can only write strings to the file. Once we are finished writing to the file, we use the close method. It is a very good idea to close a file once you are finished with it. Once a file is closed, you can no longer write to it. Here's an example:

new_file = open('writing_example.txt', 'w')
new_file.write('This sentence appears on the first line.')
new_file.write('So does this one.')
new_file.write('As does this one (but there are no spaces between these sentences...how would we have spaces between them?).')
new_file.close()

Since we just specified the file's name, this creates a file called "writing_example.txt" in the same location that Python is being run. If you want it to be written in a different location, you need to specify that! More on that below.

The contents of the file are:

This sentence appears on the first line.So does this one.As does this one (but there are no spaces between these sentences...how would we have spaces between them?).

Anything sent to the write method is written to the file.

At times, you may want to write a list of strings to a file. This is possible with the writelines method:

contents = ['This is line one.', 'This is line two.', '...', 'This is the last line.']
outfile = open('lines.txt', 'w')
outfile.writelines(contents)
outfile.close()

The contents of 'lines.txt' is:

This is line one.
This is line two.
...
This is the last line.

You can use both writelines and write on the same file.

Appending to a file

If you open a file for writing and that file already exists, it will erase the contents of the file! So, if we execute these statements:

new_file = open('writing_example.txt', 'w')
new_file.write('Here is new content.\n')
new_file.write('The old content is erased!')
new_file.close()

"writing_example.txt" will now contain only:

Here is new content.
The old content is erased!

If you just want to add on to the end of a file, you can open the file to append by passing 'a' instead of 'w' to open:

new_file = open('writing_example.txt', 'a')
new_file.write('Here we are adding new content to the file.\n')
new_file.write('The "old" content is still there though.')
new_file.close()

"writing_example.txt" now contains:

Here is new content.
The old content is erased!Here we are adding new content to the file.
The "old" content is still there though.

Why does "Here we are adding new content to the file." appear on the same line as "The old content is erased!"?

Other than passing in 'a' instead of 'w' to open, writing to a file and appending to a file are done the same way.

Reading from a file

To read from a file, we must first open it. To open it, we again use the open function:

file_reference = open(file_location_and_name, 'r')

Notice that this time, we're passing 'r' instead of 'w'. The 'r' means "read".

Just like with writing to files, you need to close the file after you are finished reading from it. You again use the close method.

Once our file is open, we can read from it using the read method. This method returns a string of the contents read in. This method is most often used to read in the entire file:

>>> infile = open('writing_example.txt', 'r')
>>> contents = infile.read()
>>> infile.close()
>>> print(contents)
Here is new content.
The old content is erased!Here we are adding new content to the file.
The "old" content is still there though.

You can specify the number of bytes to read in, but you would need to know how many bytes constitute the thing you want to read in. Generally, you won't know that ahead of time. However, if you want to read in a certain number of bytes, here's how to do it:

>>> infile = open('writing_example.txt', 'r')
>>> contents = infile.read(6) #read in 6 bytes
>>> print(contents)
Here i
>>> contents = infile.read(1) #read in 1 byte
>>> print(contents)
s
>>> infile.close()

Note: One byte does not always equal one character. In English, that's the case, but in some other languages that isn't the case. This is yet another reason why it is best to not read byte-by-byte in most cases.

There are two other options for reading contents from a file: readline and readlines. In both cases, they read whole lines. readline will read in just one line (from the current position in the file to the newline character) and return it as a string. readlines will read in all of the lines, each as a string, and put them in a list.

>>> infile = open('writing_example.txt', 'r')
>>> first_line = infile.readline()
>>> print(first_line)
Here is new content.

>>> #why do you think there's a blank line?
>>> remaining_lines = infile.readlines()
>>> print(remaining_lines)
['The old content is erased!Here we are adding new content to the file.\n', 'The "old" content is still there though.']
>>> infile.close()

It is very common to process each line of file, one at a time. Often, that's because each line represents one data point. To make processing each line individually, you can use a for loop with a file object:

>>> infile = open('writing_example.txt', 'r')
>>> for line in infile:
        print("This line is", len(line), "characters long.")

This line is 21 characters long.
This line is 70 characters long.
This line is 40 characters long.
>>> infile.close()
<< Previous Notes Daily Schedule Next Notes >>