Hone

Lessons · Python · the def f(x=[]) trap

The default argument that remembers

A default value is created once, when the function is defined. If it is a list or dict, every call shares the same one.

Hone is a place to practise programming. This is one of its lessons, written out in full and free to read without an account.

What it is for

This is a genuine production bug: a cache or history that quietly carries data from one request into the next. It passes every simple test and fails under real use.

How to think about it

Is this default a list, dict or set? Never use a list, dict or set as a default. Use None, and inside the function write 'if items is None: items = []'.

Worked example

def add(item, items=None):
None is immutable; safe as a default.
    if items is None:
The first call with no list...
        items = []
...gets a fresh one, every time.
    items.append(item); return items
Now two calls do not share a list.

Your turn

Fix the default so calls do not share state.

def log(msg, history=):
    if history is None:
        history = []
    history.append(msg)
    return history

The trap

def f(items=[]) looks right and works the first time. The second call finds the first call's items still there.

Practise the def f(x=[]) trap on HoneA question on it now, a coding challenge where there is one, and it is remembered for review. Free, no email needed.