I keep coming back to simple file-based projects when I want to teach someone how Python actually works. There’s something about reading and writing data that makes the language feel real rather than abstract. The golf scores program is one of those projects that covers the full stack of basics – user input, file I/O, decision logic, and structured data – all in one place.
This article walks through building a golf scores tracker from scratch. By the end, you will have a working program that reads and writes player records to a text file, calculates scoring conventions like Birdie and Bogey, and provides a menu-driven interface. The code works with Python 3 and requires no external packages.
TLDR
- Build a file-based golf score tracker using only Python built-ins
- Store records as NAME|SCORE|PAR|CONVENTION in a text file
- Calculate scoring conventions automatically from score minus par
- Implement menu-driven CRUD operations for player records
- No external libraries required – just standard Python
What is a Golf Scores Program?
A golf scores program is a data management application that tracks player names, stroke counts, hole pars, and the resulting scoring convention for each round. In Python, the simplest version stores everything in a flat text file using pipe-separated values. Each line represents one player record, and the program reads or appends to that file based on user menu selections. You can learn more about file handling patterns in Python and how functions in Python structure code cleanly in related AskPython articles.
The existing article on AskPython covers this but uses an outdated code block format. The refreshed version below keeps the same core logic while fixing formatting issues, adding proper structure, and including an FAQ section.
Golf Scoring Terminology
Before writing the code, here is a quick reference for the golf scoring conventions the program will calculate. Par is the expected number of strokes an expert player needs for a given hole, and every stroke above or below par has a name. If you want to explore how dictionary lookups work in Python for mapping difference values to names, the convention_map dictionary in the code demonstrates exactly that pattern.
- Ace: Hole completed in one stroke (only possible on par-3 holes)
- Birdie: One stroke under par
- At par: Exactly the expected number of strokes
- Bogey: One stroke over par
- Double Bogey: Two strokes over par
- Triple Bogey: Three strokes over par
- Eagle: Two strokes under par (par-4 or par-5 only)
- Albatross: Three strokes under par (rare, par-5 only)
- Condor: Four strokes under par (extremely rare)
The program stores par values of 3, 4, or 5 only. This matches typical hole designs and keeps the logic straightforward.
Program Flow and Menu
The program presents a simple text menu with four options. The user selects an option by entering a number, and the program calls the corresponding function. Here is the main loop.
print("=" * 60)
print("WELCOME TO THE GOLF SCORES PROGRAM!")
print("=" * 60)
inp = int(input(
"SELECT YOUR REQUIRED OPTION:\n"
"1: Enter new record\n"
"2: Search for a player\n"
"3: Display all records\n"
"4: Quit\n"
))
if inp == 1:
create_record()
elif inp == 2:
search_player()
elif inp == 3:
display_all()
elif inp == 4:
quit()
else:
print("Wrong input!")
============================================================
WELCOME TO THE GOLF SCORES PROGRAM!
============================================================
SELECT YOUR REQUIRED OPTION:
1: Enter new record
2: Search for a player
3: Display all records
4: Quit
Creating, Searching, and Displaying Records
The create_record function prompts the user for the player name, stroke count, and hole par. It then computes the scoring convention by subtracting par from the actual score. The search_player function reads through the file line by line and prints any matching records. The display_all function opens the file and prints every record in a formatted table header.
FILENAME = "scoresforgolf.txt"
def create_record():
num_records = int(input("How many records do you want to add? "))
with open(FILENAME, "a") as f:
for _ in range(num_records):
name = input("Enter the name of player: ")
score = int(input("Enter score of player: "))
par = int(input("Enter par (3, 4, or 5): "))
if score == 1:
convention = "Ace!"
elif par not in (3, 4, 5):
print("Invalid par value.")
continue
else:
diff = score - par
convention_map = {
-4: "Condor",
-3: "Albatross (Double Eagle)",
-2: "Eagle",
-1: "Birdie",
0: "At par",
1: "Bogey",
2: "Double Bogey",
3: "Triple Bogey",
4: "Quadruple Bogey",
}
convention = convention_map.get(diff, "-")
f.write(f"{name}|{score}|{par}|{convention}\n")
print("Record(s) created successfully.")
def search_player():
search_name = input("Enter the name of player: ")
with open(FILENAME, "r") as f:
found = False
for line in f:
fields = line.strip().split("|")
if fields[0].lower() == search_name.lower():
print(f"Name: {fields[0]}, Score: {fields[1]}, "
f"Par: {fields[2]}, Convention: {fields[3]}")
found = True
break
if not found:
print("Player not found.")
def display_all():
with open(FILENAME, "r") as f:
print("NAME | SCORE | PAR | SCORING CONVENTION")
print("-" * 45)
for line in f:
fields = line.strip().split("|")
if len(fields) == 4:
print(f"{fields[0]:<8} | {fields[1]:<5} | {fields[2]:<3} | {fields[3]}")
How many records do you want to add? 1
Enter the name of player: Charlie
Enter score of player: 6
Enter par (3, 4, or 5): 3
Record(s) created successfully.
Enter the name of player: Eva
Name: Eva, Score: 1, Par: 3, Convention: Ace!
NAME | SCORE | PAR | SCORING CONVENTION
---------------------------------------------
Mark | 5 | 4 | Bogey
Celine | 9 | 5 | Quadruple Bogey
Eva | 1 | 3 | Ace!
Charlie | 6 | 3 | Triple Bogey
Complete Program
Putting all the functions together with the main menu gives you a complete, self-contained golf scores tracker. The file scoresforgolf.txt is created automatically when the first record is added.
FILENAME = "scoresforgolf.txt"
def create_record():
num_records = int(input("How many records do you want to add? "))
with open(FILENAME, "a") as f:
for _ in range(num_records):
name = input("Enter the name of player: ")
score = int(input("Enter score of player: "))
par = int(input("Enter par (3, 4, or 5): "))
if score == 1:
convention = "Ace!"
elif par not in (3, 4, 5):
print("Invalid par value.")
continue
else:
diff = score - par
convention_map = {
-4: "Condor", -3: "Albatross (Double Eagle)",
-2: "Eagle", -1: "Birdie", 0: "At par",
1: "Bogey", 2: "Double Bogey",
3: "Triple Bogey", 4: "Quadruple Bogey",
}
convention = convention_map.get(diff, "-")
f.write(f"{name}|{score}|{par}|{convention}\n")
print("Record(s) created successfully.")
def search_player():
search_name = input("Enter the name of player: ")
with open(FILENAME, "r") as f:
for line in f:
fields = line.strip().split("|")
if fields[0].lower() == search_name.lower():
print(f"{fields[0]}|{fields[1]}|{fields[2]}|{fields[3]}")
return
print("Player not found.")
def display_all():
with open(FILENAME, "r") as f:
print("NAME | SCORE | PAR | SCORING CONVENTION")
for line in f:
fields = line.strip().split("|")
if len(fields) == 4:
print(f"{fields[0]}|{fields[1]}|{fields[2]}|{fields[3]}")
# Main menu
print("=" * 60)
print("WELCOME TO THE GOLF SCORES PROGRAM!")
print("=" * 60)
inp = int(input(
"1: Enter new record\n"
"2: Search for a player\n"
"3: Display all records\n"
"4: Quit\n"
))
if inp == 1:
create_record()
elif inp == 2:
search_player()
elif inp == 3:
display_all()
elif inp == 4:
print("Goodbye!")
else:
print("Wrong input!")
============================================================
WELCOME TO THE GOLF SCORES PROGRAM!
============================================================
1: Enter new record
2: Search for a player
3: Display all records
4: Quit
1
How many records do you want to add? 1
Enter the name of player: Sam
Enter score of player: 4
Enter par (3, 4, or 5): 4
Record(s) created successfully.
The program stays under 100 lines of clear, readable Python. Each function handles one responsibility, and the main menu acts as a simple controller that routes to the right function based on user input. This pattern of separating concerns across functions is a core idea behind classes and objects in Python, where each class groups related behavior and data together.
FAQ
Q: Can the program handle more than one record per player?
Yes. The search function finds the first matching record by name. To track multiple rounds for the same player, you could modify the search to collect all matching lines or add a date field to each record.
Q: What happens if the file scoresforgolf.txt does not exist?
The search and display functions will raise a FileNotFoundError if the file does not exist. You can add a check at the start of those functions using os.path.exists to handle this gracefully.
Q: Can par values other than 3, 4, or 5 be used?
The current implementation validates par to these three values only. You can extend the convention_map dictionary to handle par-6 holes if needed, though those are uncommon on standard courses.
Q: How would you extend this program to use a database instead of a text file?
Replace the file open/read/write calls with SQLite using the standard library sqlite3 module. Create a table with columns for name, score, par, and convention, then swap the file operations for SQL INSERT, SELECT, and UPDATE statements.
Conclusion
The golf scores program is a practical way to practice file I/O, string parsing, and conditional logic in Python. The core loop of reading input, making decisions, and writing data maps directly to how real Python applications work. I have used variations of this project to introduce beginners to the standard library and to demonstrate how text files can replace a database for simple use cases. The code runs on any Python 3 installation without additional packages, which makes it easy to share and experiment with.

