2025, Dec 03 13:00

Build a Python dict from key–value functions with a single call per element

Build a Python dict from (key, value) tuples and avoid double calls in dict comprehensions. Use a generator or map to guarantee one function call per item.

Transforming a sequence into a dict is straightforward when you already have key–value pairs. It gets tricky when each pair comes from a function that returns both parts together, especially if that function is expensive, stateful, or remote. In such cases, calling it twice per item inside a dict comprehension is off the table. Here is the clean way to get k: v from a single invocation per element.

Problem setup

Assume a function returns a tuple containing the dictionary key and value derived from a string. List and set comprehensions behave well with such pairs, but a naive dict comprehension tends to call the function twice per element. That’s exactly what we want to avoid.

def kv_pair(txt):             # placeholder for an expensive or stateful function
    return txt[0], txt[1:]

print([kv_pair(x) for x in ['abcd', 'efg', 'hi']])
print({kv_pair(x) for x in ['abcd', 'efg', 'hi']})
print({kv_pair(x)[0]: kv_pair(x)[1] for x in ['abcd', 'efg', 'hi']})

The list and set versions do a single call per element and work as intended. The dict comprehension shown above produces the desired mapping but calls the function twice for each item, which is unacceptable when the function is costly or depends on side effects.

Why the dict comprehension misbehaves

In a standard dict comprehension like k: v for item in data, both the key expression and the value expression are evaluated independently. Writing kv_pair(x)[0] for the key and kv_pair(x)[1] for the value triggers two separate calls. If the function is expensive, stateful, or executed remotely, that duplicates work and can even yield inconsistent results.

The fix: build the dict from an iterable of tuples

The dict constructor accepts an iterable of two-item tuples, where each tuple is interpreted as key and value. This lets you call the function exactly once per element and hand its tuple straight to dict. The simplest pattern uses a generator expression:

print(dict(kv_pair(x) for x in ['abcd', 'efg', 'hi']))

This evaluates kv_pair(x) once per element, produces tuples like ('a', 'bcd'), and lets dict turn them into {'a': 'bcd', ...}. A compact equivalent uses map with the same effect:

print(dict(map(kv_pair, ['abcd', 'efg', 'hi'])))

If you want to see it run online, here is a working demo: https://www.online-python.com/ME7cP0L6Hw.

When you don’t need the function at all

If the key and value are already available inline from the input itself, build them directly in the comprehension without calling another function. For example, if the mapping is simply first-character to the rest of the string, the structure is obvious and doesn’t require an extra indirection.

Why this matters

Minimizing calls safeguards performance and correctness when your function is heavy, stateful, or remote. Constructing a dict from an iterable of tuples keeps your transformation single-pass, clear, and predictable. It also reads well, making intent apparent to anyone scanning the code.

Takeaway

When a single function returns both key and value, route its output directly into dict. Use dict(kv_pair(x) for x in data) or dict(map(kv_pair, data)) to guarantee one invocation per element. Reserve direct key/value construction inside the comprehension for cases where you can compute k and v without touching that function. This small adjustment prevents unnecessary duplication of work and keeps your data transformations tight and reliable.