My function keeps returning results from the previous call and I cannot see how
I wrote something like def add_row(row, rows=[]) which appends the row and returns rows. Called once it is correct, called a second time it comes back with the first call's row still in it, and I am not storing anything between calls anywhere that I can see. This is a small script that reads a CSV and builds a list per file, so the leak between calls is producing nonsense output. What is actually happening here?
@listcomp_leo · 2mo ago · 3 replies
The default value is created once, when the def line runs, not each time you call the function. So there is exactly one list living on the function object, and every call that does not pass its own list appends to that same one. The fix is the None sentinel: take rows=None as the default, and on the first line of the body do rows = [] if rows is None else rows. Same trap applies to dicts, sets and anything else mutable you put in a default.
Reply
Report
@listcomp_leo · 2mo ago
Almost everyone assumes that. You can even see it — print add_row.defaults after a couple of calls and you will watch the list grow.
Reply
Report
@csv_apologist · 2mo ago
Created once at def time is the piece I did not have. I assumed the default was re-evaluated on every call.
Reply
Report