Objects Working Together · practice
Hold a Collection of Objects
A single Question is not a quiz. A quiz is several of them, in an order somebody chose, with a title on the front.
You already know how to keep several things: a
A list inside a class
_questions is internal, for the reasons Chapter 5 gave. What the outside world gets instead is add, a count, and a total. Every one of those is about the quiz, not about the list.
Look at total_points. It Question objects and asks each for its own points. The Quiz never learns how a question decides what it is worth, and would keep working if that became a computed property tomorrow.
Iterating a collection of objects
A loop over objects looks exactly like a loop over numbers. The difference is what you can do inside it:
That worked, and it reached straight past the class into _questions. In real code that line is a warning sign. If the outside world needs to walk the questions, the quiz should offer a way that does not depend on the collection being a list:
Chapter 11 gives a much better way to write this, by making the quiz itself something a for loop understands. For now a
Returning a copy, and why
questions() returns list(self._questions), not self._questions. That one call matters:
The caller removed an item from the list it was given, and the quiz still reports both questions. Return the internal list directly and that same pop() would have silently thrown away one of the quiz’s questions, through a
This is the
Why does questions() return list(self._questions) rather than self._questions?
Note what list() does and does not protect. The new list is separate, so adding and removing cannot reach the quiz. The Question objects inside it are the same objects, so a caller could still change one of them. Chapter 8 comes back to that with values that cannot be changed at all.
The exercise
You are building the Quiz that the rest of the chapter uses. It holds questions, reports on them, and does not hand out the list that controls its membership. The copy still contains the same Question objects, exactly as the shallow-copy explanation above says.
Task
Finish the collection boundary of the supplied Quiz class.
add(question) appends a question and refuses None with a questions() returns the questions in order in a new
question_at, question_count, total_points, and hardest are supplied so you can concentrate on the one new difficulty: owning a collection safely.
Run the program and confirm the final line is 3: removing an item from the list returned by questions() must leave the quiz with all three questions.