Exit slides Esc

Files

Slide 1 of 47

  1. A tournament scoreboard disappears when its program stops. Your challenge is to save scores in a file, load them into useful Python values, and find a player in a saved roster.

    Every example writes its own known data before reading it, so you can run the notebook again safely.

    • Save text in a file and read it back later.

    • Use with open(...) so a file closes when the work is done.

    • Read saved lines one at a time, clean them, and turn numbers into integers.

    • Save and load records, then search a saved roster.

  2. Lesson 1: Save Scores, Then Load Them Back

    The tournament director wants the scoreboard to survive after the program stops. We will write one score per line, then read the whole saved file back as text.

  3. Write one line to a file

    open(path, "w") opens a fresh file for writing. A file stores text, so f.write("840\n") saves the digits and a newline. The with statement closes the file when its indented block ends.

  4. with open("lesson_l1_one.txt", "w") as f:
        f.write("840\n")

    "w" creates a fresh file, and with closes it after the indented write.

  5. Read the whole file

    Open the same known file in "r" mode and use f.read() to get all its text. For this first lesson, f.read() loads the whole file as one text string. Line-by-line reading begins in Lesson 2.

  6. with open("lesson_l1_one.txt", "r") as f:
        print(f.read())

    Output

    840
    
    

    The saved 840 prints with an extra blank line because the text already ends in \n and print adds its own newline.

  7. Write several scores

    \n is the newline character inside a string. A loop writes one line per score, and the f-string changes each number to text.

  8. with open("lesson_l1_scores.txt", "w") as f:
        for score in [840, 920, 775]:
            f.write(f"{score}\n")

    The file now has three separate score lines. A later "w" write replaces all three.

  9. Put the save and load steps in functions

    These functions accept a list and a path, save each score, and return the file's complete text. A second call uses "w" on the same path to replace its earlier contents.

  10. # Save every score on its own line.
    def save_scores(scores, path):
        with open(path, "w") as f:
            for score in scores:
                f.write(f"{score}\n")
        return path
    
    def load_score_text(path):
        with open(path, "r") as f:
            text = f.read()
        return text
    
    def score_text_round_trip(scores, path):
        save_scores(scores, path)
        return load_score_text(path)
    
    print(score_text_round_trip([840, 920, 775], "lesson_l1_scores.txt"))
    print(score_text_round_trip([610, 990], "lesson_l1_scores.txt"))

    Output

    840
    920
    775
    
    610
    990
    
    
  11. The first function call saves three lines and returns 840\n920\n775\n. The second replaces that file with two known lines before reading it again. Mode "w" means write a fresh file. Mode "r" means read an existing file.

  12. Why use with?

    Here is the old way in function form. The programmer has to remember a separate close() call.

  13. def save_one_score_old_way(score, path):
        f = open(path, "w")
        f.write(f"{score}\n")
        f.close()
        return path
    
    print(save_one_score_old_way(730, "lesson_l1_old_way.txt"))

    Output

    lesson_l1_old_way.txt
    
  14. The worked call prints lesson_l1_old_way.txt because that path is the function's result, and it leaves 730 on one line in the file. The better form is with open(path, "w") as f:. with closes the file for you automatically, even if your code crashes or you forget close(). We will use with for every remaining file operation.

  15. Add to the end with "a"

    Start a known file with "w", then reopen it in "a" mode to append a later score.

  16. with open("lesson_l1_append.txt", "w") as f:
        f.write("575\n")
    with open("lesson_l1_append.txt", "a") as f:
        f.write("905\n")
    with open("lesson_l1_append.txt", "r") as f:
        print(f.read(), end="")

    Output

    575
    905
    

    "w" starts a fresh file; "a" keeps what is there and adds at the end. The file prints 575 and then 905.

  17. Try real score input

    This version reads a count and that many scores from the keyboard, saves them, then prints the reloaded text.

  18. Try it
    n = int(input("How many scores? "))
    with open("lesson_l1_input.txt", "w") as f:
        for i in range(n):
            score = int(input("Score: "))
            f.write(f"{score}\n")
    with open("lesson_l1_input.txt", "r") as f:
        print(f.read(), end="")

    Entering scores saves them in a file before the final print reads them back.

  19. Lesson 2: Turn Saved Lines into Score Statistics

    The scoreboard file is readable, but a statistics tool cannot add text such as "840". It needs to clean each saved line and turn it into an integer. Then it can update a statistic immediately or rebuild a list for Python's built-in tools.

  20. Read one line at a time

    for line in f: visits each line in order. line.strip() removes its newline, and int(...) changes the cleaned text into an integer. The append step transforms each file line into one list item.

  21. def save_number_lines(scores, path):
        with open(path, "w") as f:
            for score in scores:
                f.write(f"{score}\n")
        return path
    
    def load_number_lines(path):
        loaded_scores = []
        with open(path, "r") as f:
            for line in f:
                score = int(line.strip())
                loaded_scores.append(score)
        return loaded_scores
    
    def number_line_round_trip(scores, path):
        save_number_lines(scores, path)
        return load_number_lines(path)
    
    print(number_line_round_trip([14, 21, 18], "lesson_l2_numbers.txt"))
    print(number_line_round_trip([32, 27], "lesson_l2_numbers.txt"))

    Output

    [14, 21, 18]
    [32, 27]
    
  22. Keep a running total

    Save the known scores, turn each saved line into an integer, and add it to total as it is read.

  23. def running_total_from_file(scores, path):
        save_number_lines(scores, path)
        total = 0
        with open(path, "r") as f:
            for line in f:
                score = int(line.strip())
                total = total + score
        return total
    
    print(running_total_from_file([420, 680, 510, 735], "lesson_l2_total.txt"))

    Output

    2345
    

    running_total_from_file reports 2345 after adding the four saved scores.

  24. Count scores that reach a target

    Keep count at zero until a saved score meets the target. Increase it only for qualifying scores.

  25. def count_from_file(scores, target, path):
        save_number_lines(scores, path)
        count = 0
        with open(path, "r") as f:
            for line in f:
                score = int(line.strip())
                if score >= target:
                    count = count + 1
        return count
    
    print(count_from_file([420, 680, 510, 735], 600, "lesson_l2_count.txt"))

    Output

    2
    

    count_from_file reports 2 scores at least 600. It does not need a separate list.

  26. Keep the best score so far

    Start best with the first known score, then replace it only when a larger saved score appears.

  27. def best_score_from_file(scores, path):
        save_number_lines(scores, path)
        best = scores[0]
        with open(path, "r") as f:
            for line in f:
                score = int(line.strip())
                if score > best:
                    best = score
        return best
    
    print(best_score_from_file([420, 680, 510, 735], "lesson_l2_best.txt"))

    Output

    735
    

    best_score_from_file reports 735 with a direct file loop rather than max.

  28. Compare built-in statistics

    Another approach rebuilds an integer list from the file and then calls min, max, sum, and len.

  29. def built_in_stats_from_file(scores, path):
        save_number_lines(scores, path)
        loaded_scores = load_number_lines(path)
        return [min(loaded_scores), max(loaded_scores), sum(loaded_scores), len(loaded_scores)]
    
    print(built_in_stats_from_file([420, 680, 510, 735], "lesson_l2_builtins.txt"))

    Output

    [420, 735, 2345, 4]
    

    built_in_stats_from_file reports [420, 735, 2345, 4] after rebuilding the list.

  30. Try real score input

    This version reads a target and a count, saves that many entered scores, then counts qualifying saved lines.

  31. Try it
    target = int(input("Target: "))
    n = int(input("How many scores? "))
    with open("lesson_l2_input.txt", "w") as f:
        for i in range(n):
            score = int(input("Score: "))
            f.write(f"{score}\n")
    count = 0
    with open("lesson_l2_input.txt", "r") as f:
        for line in f:
            if int(line.strip()) >= target:
                count = count + 1
    print(count)

    The target is compared with numbers reloaded from the file, not just the entered text.

  32. Lesson 3: Save Records and Search a Roster

    A coach needs more than a bare score. One saved player record must keep a name, a level, and points together. The coach also needs a search tool that checks roster lines in order and returns as soon as it finds the requested player.

  33. One record across several lines

    This simple format uses three lines for one record: name first, then level, then points. The loader cleans every line. It keeps the name as text and transforms the remaining fields into integers before appending them to one record list.

    f.readline() reads just the NEXT line and moves on, so a following for line in f: continues from the line after it.

  34. def save_player_record(name, level, points, path):
        with open(path, "w") as f:
            f.write(f"{name}\n")
            f.write(f"{level}\n")
            f.write(f"{points}\n")
        return path
    
    def load_player_record(path):
        record = []
        with open(path, "r") as f:
            name = f.readline().strip()
            record.append(name)
            for line in f:
                number = int(line.strip())
                record.append(number)
        return record
    
    def player_record_round_trip(name, level, points, path):
        save_player_record(name, level, points, path)
        return load_player_record(path)
    
    print(player_record_round_trip("Mina", 4, 860, "lesson_l3_record.txt"))
    print(player_record_round_trip("Omar", 6, 1040, "lesson_l3_record.txt"))

    Output

    ['Mina', 4, 860]
    ['Omar', 6, 1040]
    
  35. One record per line, fields split by commas

    When a whole record fits on one line, split(",") separates its fields at the commas.

  36. line = "Mina,4,860"
    parts = line.split(",")
    print(parts)

    Output

    ['Mina', '4', '860']
    

    The three fields are still strings: ['Mina', '4', '860'].

  37. Turn a field into a number

    Use its position in parts and int when the points field needs arithmetic.

  38. print(int(parts[2]))

    Output

    860
    

    int(parts[2]) prints the number 860, not the text "860".

  39. Walk saved comma records

    Save three known records first. Then split each reloaded line and print its name field.

  40. with open("lesson_l3_commas.txt", "w") as f:
        f.write("Mina,4,860\n")
        f.write("Omar,6,1040\n")
        f.write("Nia,3,720\n")
    with open("lesson_l3_commas.txt", "r") as f:
        for line in f:
            parts = line.strip().split(",")
            print(parts[0])

    Output

    Mina
    Omar
    Nia
    

    The saved records print Mina, Omar, and Nia in file order.

  41. Search for the first matching line

    A linear search checks one line, then the next. Equality with == asks whether the cleaned line matches the target exactly. A matching line returns immediately. The not-found return belongs after the loop because the function must check every line before giving up.

  42. def save_roster(names, path):
        with open(path, "w") as f:
            for name in names:
                f.write(f"{name}\n")
        return path
    
    def find_player(target, path):
        with open(path, "r") as f:
            for line in f:
                if line.strip() == target:
                    return f"Found {target}."
        return f"{target} was not found."
    
    def roster_search(names, target, path):
        save_roster(names, path)
        return find_player(target, path)
    
    print(roster_search(["Ari", "Bo", "Chen"], "Bo", "lesson_l3_roster.txt"))
    print(roster_search(["Ari", "Bo", "Chen"], "Devi", "lesson_l3_roster.txt"))

    Output

    Found Bo.
    Devi was not found.
    
  43. The first search returns Found Bo. from inside the loop. The second checks all three lines, then reaches the fallback after the loop and returns Devi was not found.

  44. Try real roster input

    This version reads a target name and a count, saves that many entered names, and searches the reloaded roster.

  45. Try it
    target = input("Name to find: ")
    n = int(input("How many names? "))
    with open("lesson_l3_input.txt", "w") as f:
        for i in range(n):
            name = input("Name: ")
            f.write(f"{name}\n")
    result = f"{target} was not found."
    with open("lesson_l3_input.txt", "r") as f:
        for line in f:
            if line.strip() == target:
                result = f"Found {target}."
                break
    print(result)

    The search checks saved names in order and prints the first match or the not-found message.

    • open(path, 'w') starts a fresh file; 'a' adds to its end.

    • with open(path, 'r') as f: opens a file for reading and closes it afterward.

    • for line in f: visits saved lines; int(line.strip()) turns a number line into an integer.

    • line.split(',') separates the fields of a comma record.

    • A search checks saved names in order and reports a match or a not-found result.

    You can now save a tournament scoreboard and search a saved roster.