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 thatrepr(),print(), and f-strings produce useful output for your objects - Implement
__eq__to define what "equal" means for your class, and use@functools.total_orderingto get all comparison operators from__eq__and__lt__ - Implement
__len__,__getitem__, and__contains__to make your collection work withlen(), indexing, and theinoperator - Implement
__iter__and__next__to make your collection work withforloops, list comprehensions, and functions likeany()andall() - Implement
__hash__to make your objects usable as dictionary keys and set members, and__bool__to define truthiness
Chapter Lessons
| Lesson | Title | What You Do | Duration |
|---|---|---|---|
| 1 | Display: repr and str | Implement __repr__ for unambiguous developer output and __str__ for human-friendly display. Learn when Python calls which. | 20 min |
| 2 | Comparison: eq and Ordering | Define value equality with __eq__ and get all six comparison operators from @functools.total_ordering. | 20 min |
| 3 | Container: len, getitem, contains | Make NoteCollection support len(), indexing with [], and membership testing with in. | 20 min |
| 4 | Iteration: iter and next | Make NoteCollection support for loops, list comprehensions, and generator-based iteration. | 20 min |
| 5 | Hashability and the Capstone | Make Note usable in sets and as dict keys with __hash__. Add __bool__ for truthiness. Integrate all special methods in the capstone. | 20 min |
| 6 | Chapter 60 Quiz | 20 scenario-based questions covering all five lessons | 25 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.
| Stage | What You Do | Claude 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 |
| Run | Press 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 |
| Investigate | Read 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 |
| Modify | Add 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 |
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 usingself(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__()andNote.__str__()soprint(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__()solen(collection)andnote in collectionwork - Lesson 4 (Iteration):
NoteCollection.__iter__()sofor note in collection:works - Lesson 5 (Hashability + Capstone):
Note.__hash__()and__bool__()plus full integration