Initializing Dictionaries in Python: Key Sequence Factory with fromkeys()

The dict.fromkeys(iterable[, value=None]) class method creates a new dictionary whose keys are drawn from an iterable, with all keys initialized to the specified value (defaulting to None).

The Shared Mutable Pitfall: When passing a mutable object (such as an empty list [] or sub-dictionary {}) as the default value, all keys share the exact same object reference in memory. Modifying the list for one key will mutate it for all keys. Use a dictionary comprehension when each key requires an independent container.

1. Method Syntax & Signature 🔝

The standard CPython signature for dict.fromkeys() is:

dict.fromkeys(iterable, value=None)
Parameter Type Default Behavior & Description
iterable Iterable[Hashable] Required An iterable yielding unique, hashable objects to be used as dictionary keys (e.g., list, tuple, set, range, string).
value Any object None The initial value assigned to every key. If omitted, defaults to None.
Return Value dict — A new dictionary populated with keys from the iterable, all initialized to value.

2. Initializing with Default and Custom Values 🔝

You can initialize keys with the default None or provide an immutable primitive such as an integer, string, or boolean:

Basic Factory Creation
fields = ["name", "email", "phone"]

# 1. Without value parameter: defaults to None
empty_record = dict.fromkeys(fields)
print("Default None:  ", empty_record)
# Output: {'name': None, 'email': None, 'phone': None}

# 2. With immutable default value
flags = dict.fromkeys(["is_admin", "is_verified", "is_banned"], False)
print("Boolean flags: ", flags)
# Output: {'is_admin': False, 'is_verified': False, 'is_banned': False}

3. The Infamous Shared Mutable Reference Trap 🔝

One of Python's most notorious beginner bugs occurs when passing a mutable container (such as a list [] or dictionary {}) to dict.fromkeys(). Because Python evaluates the argument once, every key references the exact same list in memory:

The Shared Mutable Bug Exposed
# BUG: All keys reference the SAME empty list!
buggy_dict = dict.fromkeys(["team_a", "team_b"], [])

# Append a player to team_a
buggy_dict["team_a"].append("Alice")

# Disaster: team_b was also modified!
print("team_a:", buggy_dict["team_a"])  # ['Alice']
print("team_b:", buggy_dict["team_b"])  # ['Alice'] (unintended side effect!)
print("Identity check:", buggy_dict["team_a"] is buggy_dict["team_b"])  # True

4. The Solution: Dictionary Comprehensions 🔝

Whenever you need each key to possess an independent, fresh container, use a dictionary comprehension instead of fromkeys(). The comprehension instantiates a new object on every iteration:

Correct Solution: Independent Allocations
# Each key gets its own unique, newly instantiated list
clean_dict = {k: [] for k in ["team_a", "team_b"]}

clean_dict["team_a"].append("Alice")

print("team_a:", clean_dict["team_a"])  # ['Alice']
print("team_b:", clean_dict["team_b"])  # [] (properly empty!)
print("Identity check:", clean_dict["team_a"] is clean_dict["team_b"])  # False

5. Initializing from Diverse Key Iterables 🔝

dict.fromkeys() accepts any iterable yielding hashable objects, including ranges, strings, and generator expressions:

# 1. From a numeric range
counters = dict.fromkeys(range(1, 5), 0)
print("Range keys: ", counters)  # {1: 0, 2: 0, 3: 0, 4: 0}

# 2. From a string (splits into individual character keys)
char_presence = dict.fromkeys("aeiou", True)
print("Vowel lookup:", char_presence)  # {'a': True, 'e': True, 'i': True, 'o': True, 'u': True}

6. Real-World Engineering Recipes 🔝

Recipe 1: Order-Preserving Fast Deduplication

The standard CPython hash table implementation preserves insertion order. Calling dict.fromkeys() deduplicates sequences in O(N) time while preserving order (unlike set() which randomizes order):

def deduplicate_preserve_order(items: list) -> list:
    return list(dict.fromkeys(items))

raw_tags = ["python", "fastapi", "python", "docker", "fastapi"]
unique_tags = deduplicate_preserve_order(raw_tags)
print("Clean tags:", unique_tags)  # ['python', 'fastapi', 'docker']

Recipe 2: Generating Default Schema Blueprints

Initialize uniform default templates for database rows or API response models:

def create_record_template(columns: list[str], default_val="") -> dict:
    return dict.fromkeys(columns, default_val)

user_columns = ["id", "first_name", "last_name", "phone"]
template = create_record_template(user_columns, None)
print("Template blueprint:", template)

7. Common Pitfalls & Boundary Traps 🔝

Trap 1: Mutable Default Reference Sharing

Never write dict.fromkeys(keys, []) or dict.fromkeys(keys, {}). The single list or dictionary instance is shared across every key. Use {k: [] for k in keys} instead.

Trap 2: Passing a Single String Splits into Characters

Strings are iterables in Python. Calling dict.fromkeys("user_id", 0) does not create a dictionary with the key "user_id" — it creates keys 'u', 's', 'e', 'r', '_', 'i', 'd'. Wrap single strings in a list: dict.fromkeys(["user_id"], 0).

8. Production Test Suite & Self-Checking Assertions 🔝

Run this complete test harness verifying default assignments, deduplication, and mutable independence:

FromkeysVerifier Test Harness
class FromkeysVerifier:
    @staticmethod
    def init_blueprint(fields: list, default_value=None) -> dict:
        return dict.fromkeys(fields, default_value)

    @staticmethod
    def deduplicate_seq(seq: list) -> list:
        return list(dict.fromkeys(seq))

# Verification unit assertions
v = FromkeysVerifier()

# Test 1: None default initialization
d1 = v.init_blueprint(["a", "b"])
assert d1 == {"a": None, "b": None}

# Test 2: Custom immutable default
d2 = v.init_blueprint(["x", "y"], 0)
assert d2 == {"x": 0, "y": 0}

# Test 3: Fast order-preserving deduplication
raw_data = [1, 2, 1, 3, 2, 4]
assert v.deduplicate_seq(raw_data) == [1, 2, 3, 4]

print("All dict.fromkeys() unit assertions passed successfully!")

Practice in Google Colab & GitHub 🔝

Open in Google Colab View on GitHub

Run all dictionary fromkeys exercises interactively, test default initialization, observe the shared mutable bug and its comprehension solution, and verify assertions in Google Colab.




Subscribe to our YouTube Channel here



plus2net.com







Python Video Tutorials
Python SQLite Video Tutorials
Python MySQL Video Tutorials
Python Tkinter Video Tutorials
✖
We use cookies to improve your browsing experience. . Learn more
HTML MySQL PHP JavaScript ASP Photoshop Articles Contact us
© 2000-2026 plus2net.com All rights reserved worldwide Privacy Policy Disclaimer