Exercise 1: A MovingAverageTracker Observer — Possible Solution ==================================================================== THE NEW OBSERVER ------------------------------ class MovingAverageTracker: def __init__(self): self.prices = [] def update(self, symbol, price): self.prices.append(price) def average(self): return sum(self.prices) / len(self.prices) Follows this chapter's own observer shape exactly - a single update(symbol, price) method matching PriceLogger and AlertService's own signature, so Stock's _notify() loop can call it identically to every other attached observer without any special-casing. VERIFYING IT ALONGSIDE THE EXISTING OBSERVERS ------------------------------ Attaching logger, alert, AND tracker to the same Stock('ACME', 100), then sending three price updates (120, 160, 140): tracker prices: [120, 160, 140] tracker average: 140.0 manual average: (120+160+140)/3 = 140.0 All three observers received all three notifications - tracker's own average is confirmed to match a manual calculation exactly, computed independently of whatever logger and alert were doing with the same three notifications. WHY THIS DEMONSTRATES OBSERVER'S OWN VALUE FURTHER ------------------------------ Stock's own set_price()/_notify() code needed zero changes to support a third, differently-behaved observer - exactly the same finding this chapter already established with two observers, now confirmed to hold for three. Each observer keeps its own private state (a log list, an alerts list, a running price list) completely independently; Stock never needs to know any of that exists. WHY THIS WORKS AS AN ANSWER ------------------------------ The new observer matches the established update(symbol, price) interface exactly, is verified running alongside the two existing observers rather than in isolation, and its own computed result is cross-checked against a manual calculation.