make_id_generator() that, when called, returns a function next_id(_cache=[]) where _cache is used purely to demonstrate that default argument objects are created exactly once at function-definition time and persist across calls. next_id should append len(_cache) to _cache (using the current length as the next id before appending) and return that id. Show correct usage: creating the generator with make_id_generator() and calling the returned next_id() repeatedly should yield 0, 1, 2, ... in sequence, since the mutable default is deliberately reused here as internal state (a case where relying on the mutable-default quirk is intentional and documented, unlike the earlier bug-fix problem).next_id = make_id_generator() next_id() next_id() next_id()
0, 1, 2
Each call appends the current length of the shared _cache list as the new id, then returns it.
A mutable default argument (like _cache=[]) is created once when the def statement inside make_id_generator runs, and that same list object is reused on every call to that particular next_id.
Calling make_id_generator() again creates a brand-new next_id function with its own brand-new default list, so the counters do not interfere with each other.