Batu Lab NotesPractical developer guides

Avoid eager default construction when dict.get finds an existing value

By Batu · English technical notes

Also published in our primary archive.

dict.get('mode', build_default()) does not defer build_default(): call arguments are evaluated before the call is made. To avoid creating an unused fallback, test membership explicitly and access the mapping only in the appropriate branch. This is important when a key stores None, because None can be a meaningful present value rather than evidence that the key is absent.

The first experiment uses {'mode': None}. get returns the stored None, yet the call log gains one entry because the fallback expression has already run. The correction uses if key in mapping, followed by mapping[key] for present keys. It preserves the stored None and makes zero factory calls. The absent-key control demonstrates the other branch: theme is not present, so it returns 'default' and calls the factory once. The program saves each call count at the time that branch finishes; it does not reconstruct the earlier value afterward.

Do not replace this membership test with mapping.get(key) or build_default() when falsey values are valid, since None, 0, and empty strings would incorrectly use the fallback. The assertions cover this side-effect trace only; they do not make a factory exception-safe or idempotent.

dict.get is documented to return its default for a missing key, and the language reference specifies that call argument expressions are evaluated before a call. These are long-established Python 3 behaviors with no special newer-version requirement beyond a supported Python 3 release.

AI assistance disclosure: This article was drafted with AI assistance and uses a synthetic, locally reproducible fixture.

Sources: Python mapping types — dict; Python expression calls.

calls = []


def build_default():
    calls.append("built")
    return "default"


def value_for(mapping, key):
    if key in mapping:
        return mapping[key]
    return build_default()


mapping = {"mode": None}

# Failing expression: build_default runs before dict.get receives its arguments.
eager_value = mapping.get("mode", build_default())
assert eager_value is None
assert calls == ["built"]

calls.clear()
present_value = value_for(mapping, "mode")
present_calls = len(calls)
assert present_value is None
assert present_calls == 0

absent_value = value_for(mapping, "theme")
absent_calls = len(calls)
assert absent_value == "default"
assert absent_calls == 1
print("present:", present_value, "calls:", present_calls)
print("absent:", absent_value, "calls:", absent_calls)
present: None calls: 0
absent: default calls: 1