# Exercise 20: Functions and Files

Remember your checklist for functions, then do this exercise paying close attention to how functions and files can work together to make useful stuff.

 ```from sys import argv script, input_file = argv def print_all(f): print f.read() def rewind(f): f.seek(0) def print_a_line(line_count, f): print line_count, f.readline() current_file = open(input_file) print "First let's print the whole file:\n" print_all(current_file) print "Now let's rewind, kind of like a tape." rewind(current_file) print "Let's print three lines:" current_line = 1 print_a_line(current_line, current_file) current_line = current_line + 1 print_a_line(current_line, current_file) current_line = current_line + 1 print_a_line(current_line, current_file) ```

Pay close attention to how we pass in the current line number each time we run print_a_line.

# What You Should See

```\$ python ex20.py test.txt
First let's print the whole file:

This is line 1
This is line 2
This is line 3

Now let's rewind, kind of like a tape.
Let's print three lines:
1 This is line 1

2 This is line 2

3 This is line 3
```

# Study Drills

1. Write English comments for each line to understand what that line does.
2. Each time print_a_line is run, you are passing in a variable current_line. Write out what current_line is equal to on each function call, and trace how it becomes line_count in print_a_line.
3. Find each place a function is used, and check its def to make sure that you are giving it the right arguments.
4. Research online what the seek function for file does. Try pydoc file and see if you can figure it out from there. Then try pydoc file.seek to see what seek does.
5. Research the shorthand notation += and rewrite the script to use += instead.

# Common Student Questions

What is f in the print_all and other functions?
The f is a variable just like you had in other functions in Exercise 18, except this time it’s a file. A file in Python is kind of like an old tape drive on a mainframe, or maybe a DVD player. It has a “read head,” and you can “seek” this read head around the file to positions, then work with it there. Each time you do f.seek(0) you’re moving to the start of the file. Each time you do f.readline() you’re reading a line from the file, and moving the read head to right after the \n that ends that line. This will be explained more as you go on.
Why does seek(0) not set the current_line to 0?
First, the seek() function is dealing in bytes, not lines. The code seek(0) moves the file to the 0 byte (first byte) in the file. Second, current_line is just a variable and has no real connection to the file at all. We are manually incrementing it.
What is +=?
You know how in English I can rewrite “it is” as “it’s”? Or I can rewrite “you are” as “you’re”? In English this is called a contraction, and this is kind of like a contraction for the two operations = and +. That means x = x + y is the same as x += y.
How does readline() know where each line is?
Inside readline() is code that scans each byte of the file until it finds a \n character, then stops reading the file to return what it found so far. The file f is responsible for maintaining the current position in the file after each readline() call, so that it will keep reading each line.
Why are there empty lines between the lines in the file?
The readline() function returns the \n that’s in the file at the end of that line. Add a , at the end of your print function calls to avoid adding double \n to every line.