0%

Representing and Comparing Objects · practice

Create a User-facing str()

Question("What does len('cat') return?", '3', 2) is the kind of detail a developer wants to see in a log.

It is not what you would show a learner taking the quiz. They want the prompt, and nothing else.

Python lets an answer both requests differently.

Two questions an object gets asked

Try it

Three lines, two different . print used __str__. repr() used __repr__. The used __repr__ for its contents.

The split is deliberate:

  • __repr__ is for whoever is working on the program: informative and unambiguous, with a constructor-like form when that is practical.

  • __str__ is for whoever is using the program: readable, and free to leave things out.

__str__ here omits the answer entirely, which would be a terrible repr and is exactly right for text shown to someone about to answer the question.

For these classes, plain formatting such as {question} also uses __str__. Adding !r, as in {question!r}, selects __repr__ instead.

Which output does print(f"Next: {question}") use?

What happens when you define only one

This is the part worth remembering, because it decides which to write first.

Define only __repr__, and str() falls back to it. Every display in the program improves at once:

Try it

Define only __str__, and there is no fallback in the other direction:

Try it

The list still shows the memory address, and so does every debugger, log line, and failed assertion.

When improving both developer and user displays, start with __repr__. Add __str__ when the readable form needs to differ.

Most classes never need __str__. A Response or a ScoreReport is not something you show a user directly, and giving them a __str__ that only repeats the repr is code with no reader.

Formatting belongs at the edge, mostly

Chapter 6 argued that presentation should stay out of domain classes. __str__ looks like it breaks that rule.

The distinction is . __str__ answers “what is the plainest text form of this one object?” It should not know about width, color, language, or the layout of a report. Those decisions belong to ScoreReport or to the entry point, and they change far more often.

A useful test: if the string would change when the program moved to a web page, it does not belong in __str__.

The exercise

You are adding both methods across three classes, and deciding for each one whether a __str__ earns its place.

Task

Give each class the display it actually needs.

Question gets both: a repr reading Question('...', '...', 2), and a __str__ reading What does len('cat') return? (2 points), which never reveals the answer.

QuizAttempt gets both: a summary repr reading QuizAttempt(learner='Mina', response_count=2), and a __str__ reading Mina: 2 of 5 points.

Response gets a repr only, reading Response(given='3', earned=2). Its correctness and earned points are snapshots from when the answer arrived.

Run the program. The two lines printing a must show the developer form, and the two printing a single must show the readable one.