Read the file once, use the data many times
A file handle reads forward. A for loop over it moves through the file line by line, and when the loop ends, the handle is at the end of the file. A second loop over the same handle finds no lines left, so its body doesn't run at all. Python doesn't stop with an error: the program just gives a wrong answer, which makes this mistake easy to miss.
95
88
102
91with open("laps.txt") as file:
laps = 0
for line in file:
laps += 1
total = 0
for line in file:
total += int(line)
print("Laps:", laps)
print("Total time:", total)
Laps: 4
Total time: 0There are two ways to fix it. You can open the file again for the second loop, with a second with open(...). Usually it's better to read the file once and store its contents in a list or a dictionary. A list can be looped over as many times as you like, and the rest of the program never touches the file again. With the same file:
95
88
102
91laps = []
with open("laps.txt") as file:
for line in file:
laps.append(int(line))
print("Laps:", len(laps))
print("Total time:", sum(laps))
print("Fastest:", min(laps))
for lap in laps:
if lap > 100:
print("Slow lap:", lap)
Laps: 4
Total time: 376
Fastest: 88
Slow lap: 102Reading into a dictionary
When each line is about something with a name, a dictionary is a good home for the data. In this file, each line is one customer's shopping basket: the customer's name, then everything in the basket. A function reads the file into a dictionary whose keys are the customers and whose values are lists of their items, and returns it. After that, the program asks the dictionary as many questions as it likes:
Mia;bread;milk;apples
Noah;coffee;bananas
Lena;apples;bread;cheese;milkdef read_baskets(filename):
baskets = {}
with open(filename) as file:
for line in file:
parts = line.strip().split(";")
baskets[parts[0]] = parts[1:]
return baskets
baskets = read_baskets("baskets.csv")
print(baskets["Noah"])
for customer, items in baskets.items():
print(f"{customer}: {len(items)} items")
for customer, items in baskets.items():
if "bread" in items:
print(customer, "bought bread")
['coffee', 'bananas']
Mia: 3 items
Noah: 2 items
Lena: 4 items
Mia bought bread
Lena bought breadThe slice parts[1:] is already a list: every field after the name. Here the fields are words, so the list can go into the dictionary as it is. When they are numbers, build the list with a loop that converts each field with int, as the rounds example in the previous step did, and store that list under the name. Then the numbers are converted once, while reading, and every later calculation can use them.
Two loops over the dictionary are no problem, unlike two loops over the file. And the rest of the program never sees a semicolon or a line break: only read_baskets knows what the file looks like.