← Back to Python series
🛠
Practice Projects · ★★★
OOP · JSON · Search · Borrowing system

Project 10 — Library Manager

Manage a book library with borrow/return tracking, member accounts, overdue detection, and full-text search.

OOPJSONlibrarysearchborrowing
Duration
3 hours
Level
📊 Intermediate-Advanced Applied
Prerequisite
🎯 Intermediate Weeks 7–8
OUTCOME
A multi-class library management system with borrowing and search

What you'll learn

  • 1Design a multi-class system: Book, Member, Library
  • 2Implement borrow/return with due dates
  • 3Detect overdue books and calculate fines
  • 4Full-text search by title, author, or ISBN

Classes

  • Book: isbn, title, author, category, copies_total, copies_available
  • Member: id, name, email, borrowed_books (list of {isbn, due_date})
  • Library: books (dict), members (dict), borrow/return/search methods

Commands

  • book add/list/search <query>
  • member add/list
  • borrow <member_id> <isbn>
  • return <member_id> <isbn>
  • overdue — list all overdue borrowings with fines

Common Mistakes (FAQ)

Q. Should books/members be a list or a dict?

Use a dict keyed by ISBN / member id — lookup is O(1). A list forces an O(n) scan on every borrow/return/search and makes duplicate-key bugs easy to miss.

Q. A book gets borrowed even when no copies are left.

Check copies_available > 0 before decrementing, and return a clear message otherwise. Decrement on borrow, increment on return — and guard return so copies_available never exceeds copies_total.

Q. How do I compute overdue days correctly?

Parse the stored ISO date with date.fromisoformat(due) and compare to date.today(): overdue_days = (date.today() - due).days, overdue when > 0. Don't string-compare dates for arithmetic.

Q. Adding a member/book with an existing id silently overwrites.

dict assignment replaces without warning. Check `if isbn in self.books:` first and reject (or merge copies) so you don't lose the existing record.

Q. json.dump fails on my Book/Member objects.

Objects (and dataclasses) aren't JSON-serializable directly. Convert to plain dicts on save (dataclasses.asdict, or a to_dict()), and reconstruct the objects when loading.

📝 Exercises

Try them yourself first, then open the solution to compare.

Exercise 1

Build the library manager

Goal: Implement Book, Member, and Library classes with all commands.

Requirements
  • 3 classes with clean interfaces
  • Borrow/return with due date tracking
  • Overdue detection (>14 days = overdue)
  • JSON persistence
Example code / lecture materials

All lecture materials and example code are openly available on GitHub.

View on GitHub ↗