Skip to main content

Chapter 60: Special Methods

James finishes the SmartNotes hierarchy from Chapter 59. Four classes, fifteen tests, all green. He types print(note) to check his work:

<__main__.TextNote object at 0x104a8b2d0>

"That is not useful," Emma says. "Your object does not know how to introduce itself. Python asked it for a string, and all it could say was its type and memory address."

"But I wrote methods. I wrote tests. Why can it not just print the title?"

"Because print() does not call .summarize(). It calls __str__(). And you never wrote __str__(). Python gives every object a default version that shows the memory address. If you want something useful, you write your own."

This chapter teaches you to write special methods: the double-underscore methods that Python calls behind the scenes when you use print(), ==, len(), for, in, and other built-in operations. Every lesson adds a new protocol to the SmartNotes project, and every lesson uses the TDG cycle you mastered in Phase 4.

What You Will Learn

By the end of this chapter, you will be able to:

  • Implement __repr__ and __str__ so that repr(), print(), and f-strings produce useful output for your objects
  • Implement __eq__ to define what "equal" means for your class, and use @functools.total_ordering to get all comparison operators from __eq__ and __lt__
  • Implement __len__, __getitem__, and __contains__ to make your collection work with len(), indexing, and the in operator
  • Implement __iter__ and __next__ to make your collection work with for loops, list comprehensions, and functions like any() and all()
  • Implement __hash__ to make your objects usable as dictionary keys and set members, and __bool__ to define truthiness

Chapter Lessons

LessonTitleWhat You DoDuration
1Display: repr and strImplement __repr__ for unambiguous developer output and __str__ for human-friendly display. Learn when Python calls which.20 min
2Comparison: eq and OrderingDefine value equality with __eq__ and get all six comparison operators from @functools.total_ordering.20 min
3Container: len, getitem, containsMake NoteCollection support len(), indexing with [], and membership testing with in.20 min
4Iteration: iter and nextMake NoteCollection support for loops, list comprehensions, and generator-based iteration.20 min
5Hashability and the CapstoneMake Note usable in sets and as dict keys with __hash__. Add __bool__ for truthiness. Integrate all special methods in the capstone.20 min
6Chapter 60 Quiz20 scenario-based questions covering all five lessons25 min

PRIMM-AI+ in This Chapter

Every lesson includes a PRIMM-AI+ Practice section following the five-stage cycle from Chapter 42. This is Phase 5: the TDG cycle now specifies special method interfaces that integrate your objects with Python's built-in operations.

StageWhat You DoClaude Code Tool
Predict [AI-FREE]Predict what print(note) shows, whether note1 == note2 is True, or what len(collection) returns. Press Shift+Tab for Plan Mode.Plan Mode protects prediction
RunPress Shift+Tab to exit Plan Mode. Run uv run python to check output, uv run pytest to verify special method behavior, or uv run pyright to check signatures. Compare results to your prediction.You run it, not Claude Code
InvestigateRead output or tracebacks to understand which special method Python called and why. In Claude Code, type: /investigate for Socratic questions about the protocol./investigate probes mechanics
ModifyAdd or fix a special method, then predict whether the change resolves the issue.You edit, Claude Code reviews
Make [Mastery Gate]Implement all special methods on Note and NoteCollection with TDG. In Claude Code, type: /tdg for structured TDG workflows.Your work, Claude Code guides
Starter Kit

Your PRIMM-AI+ starter kit from Chapter 42 works throughout Phase 5. Use /predict, /investigate, /bug, /debug, and /tdg commands as you work through each lesson.

Prerequisites

Before starting this chapter, you should be able to:

  • Write classes with __init__, typed parameters, and instance attributes using self (Chapter 58)
  • Write methods that read, modify (with validation), and query instance state (Chapter 58)
  • Use inheritance to create specialized subclasses and composition to build collections (Chapter 59)
  • Drive the full TDG cycle independently: specify, test, generate, verify, debug (Chapter 57)
  • Run the verification tools: uv run ruff check, uv run pyright, uv run pytest (Chapters 52-56)

The SmartNotes Connection

This chapter makes SmartNotes objects Pythonic. In Chapter 58 you built Note with __init__, methods, and attributes. In Chapter 59 you built a hierarchy with TextNote, CodeNote, LinkNote, and NoteCollection. But those objects cannot participate in Python's built-in operations: print() shows a memory address, == compares identity instead of value, len() raises TypeError, and for loops fail.

Each lesson adds a protocol that connects SmartNotes to Python's infrastructure:

  • Lesson 1 (Display): Note.__repr__() and Note.__str__() so print(note) shows useful information
  • Lesson 2 (Comparison): Note.__eq__() so two notes with the same title and body are equal
  • Lesson 3 (Container): NoteCollection.__len__(), .__getitem__(), .__contains__() so len(collection) and note in collection work
  • Lesson 4 (Iteration): NoteCollection.__iter__() so for note in collection: works
  • Lesson 5 (Hashability + Capstone): Note.__hash__() and __bool__() plus full integration