Table of contents
Implement code functionality

How to create a dictionary in Python

May 22, 2025
 ・ by  
the Anthropic Team
Table of contents
H2 Link Template
Try Claude

Python dictionaries store key-value pairs that let you organize and access data efficiently. These versatile data structures use curly braces {} and colons to map unique keys to their corresponding values, enabling fast lookups and modifications.

This guide covers essential dictionary techniques, practical examples, and troubleshooting tips—with code samples created using Claude, an AI assistant built by Anthropic.

Creating a dictionary with curly braces

person = {"name": "Alice", "age": 30, "city": "New York"}
print(person)
{'name': 'Alice', 'age': 30, 'city': 'New York'}

The dictionary in this example maps three distinct keys ("name", "age", and "city") to their respective values, creating a structured way to store related data about a person. Each key serves as a unique identifier that makes the corresponding value easily accessible.

Python dictionaries offer several advantages over using separate variables or lists for related data:

  • They keep related information organized in a single container
  • They provide semantic meaning through descriptive key names
  • They enable faster lookups compared to searching through lists
  • They maintain a clear relationship between data points

Different initialization methods

Beyond using curly braces, Python provides three powerful methods to initialize dictionaries: the dict() constructor, sequence-based creation, and dictionary comprehensions.

Using the dict() constructor

person = dict(name="Alice", age=30, city="New York")
print(person)
{'name': 'Alice', 'age': 30, 'city': 'New York'}

The dict() constructor provides a cleaner syntax for creating dictionaries when your keys are valid Python identifiers. Instead of using colons and quotes, you can pass key-value pairs as keyword arguments—similar to how you'd call a function.

  • Keys become unquoted parameter names (name=, age=, city=)
  • Values can be any valid Python expression
  • The constructor automatically converts parameter names to strings

This approach reduces visual clutter and potential syntax errors. However, it only works when dictionary keys follow Python's variable naming rules. For keys containing spaces or special characters, stick to the curly brace syntax.

Creating dictionaries from sequences

items = [("name", "Alice"), ("age", 30), ("city", "New York")]
person = dict(items)
print(person)
{'name': 'Alice', 'age': 30, 'city': 'New York'}

The dict() constructor transforms sequences of key-value pairs into dictionaries. When you pass a list of tuples to dict(), each tuple's first element becomes a key and its second element becomes the corresponding value.

  • Each tuple in the sequence must contain exactly two elements
  • The first element (key) must be immutable and hashable
  • The second element (value) can be any valid Python object

This method excels when your data already exists in a paired format. It's particularly useful when processing data from external sources or converting other data structures into dictionaries. The sequence-based approach offers more flexibility than keyword arguments since keys don't need to follow Python's identifier rules.

Using dictionary comprehensions

names = ["Alice", "Bob", "Charlie"]
scores = [95, 87, 92]
grade_dict = {name: score for name, score in zip(names, scores)}
print(grade_dict)
{'Alice': 95, 'Bob': 87, 'Charlie': 92}

Dictionary comprehensions provide a concise way to create dictionaries by transforming and filtering data. The syntax mirrors list comprehensions but uses curly braces and requires both a key and value expression.

In this example, the zip() function pairs each student name with their corresponding score. The comprehension {name: score for name, score in zip(names, scores)} then creates dictionary entries from these pairs.

  • The expression before for defines the key-value structure (name: score)
  • The part after for specifies how to iterate through the data
  • Python automatically matches each name to its score based on position

This approach streamlines dictionary creation compared to manual key assignment or using the dict() constructor. It works especially well when transforming parallel lists into key-value relationships.

Advanced dictionary techniques

Beyond these foundational techniques, Python dictionaries offer specialized methods like fromkeys(), nested structures, and defaultdict to handle complex data relationships more elegantly.

Creating dictionaries with fromkeys() method

keys = ["name", "age", "city"]
default_value = "Unknown"
person = dict.fromkeys(keys, default_value)
print(person)
{'name': 'Unknown', 'age': 'Unknown', 'city': 'Unknown'}

The fromkeys() method creates a dictionary by assigning the same value to multiple keys. This built-in function takes two arguments: an iterable containing the desired keys and a default value that each key will reference.

  • The first argument (keys) defines what keys the dictionary will contain
  • The second argument (default_value) sets the initial value for all keys
  • Python automatically maps each key to the specified default value

This approach proves particularly useful when initializing dictionaries with placeholder values or creating templates for data structures. The method saves time compared to manually assigning the same value to multiple keys.

Creating nested dictionaries

employees = {
    "Alice": {"department": "Engineering", "salary": 85000},
    "Bob": {"department": "Marketing", "salary": 75000}
}
print(employees["Alice"]["department"])
Engineering

Nested dictionaries embed one dictionary inside another, creating hierarchical data structures. The example shows an employee database where each person's name links to another dictionary containing their details.

  • Each employee (like "Alice") acts as a key that maps to their own dictionary of attributes
  • Access nested values by chaining square brackets: employees["Alice"]["department"] retrieves "Engineering"
  • This structure efficiently organizes complex, related data that belongs together

Nested dictionaries excel at representing real-world relationships where objects have multiple properties. They're particularly useful for storing structured data like employee records, product catalogs, or game character attributes.

Using defaultdict for automatic initialization

from collections import defaultdict
grades = defaultdict(list)
grades["Alice"].append(95)
grades["Alice"].append(92)
print(dict(grades))
{'Alice': [95, 92]}

defaultdict automatically creates a default value when you access a non-existent key. In this example, defaultdict(list) initializes an empty list whenever you reference a new key. This eliminates the need to check if a key exists before appending values.

  • Regular dictionaries raise a KeyError when accessing missing keys
  • defaultdict handles missing keys gracefully by creating the specified default value
  • The argument passed to defaultdict (list in this case) determines the type of default value

This functionality proves especially useful when collecting multiple values per key. The code demonstrates this by appending two grades for Alice without explicitly creating an empty list first.

Get unstuck faster with Claude

Claude is an AI assistant created by Anthropic that helps developers write, understand, and debug Python code. It combines deep technical knowledge with clear, natural communication to guide you through programming challenges.

Working alongside you like an experienced mentor, Claude can explain complex dictionary operations, suggest optimal data structures, or help troubleshoot error messages. It provides contextual guidance while helping you understand the underlying concepts.

Start accelerating your Python development today. Sign up for free at Claude.ai to get personalized help with dictionaries, data structures, and any other programming questions.

Some real-world applications

Python dictionaries power essential programming tasks like tracking word frequencies and optimizing recursive functions through strategic data caching.

Counting word frequencies using .get() method

The .get() method enables efficient word frequency counting by safely retrieving dictionary values with a default fallback, eliminating the need for explicit key existence checks.

text = "the quick brown fox jumps over the lazy dog"
word_count = {}
for word in text.lower().split():
    word_count[word] = word_count.get(word, 0) + 1
print(word_count)

This code creates a dictionary that tracks how many times each word appears in a text string. The text.lower().split() converts the string to lowercase and breaks it into individual words. For each word, the code uses .get() to either retrieve its current count or return 0 if the word isn't in the dictionary yet.

  • The dictionary word_count stores words as keys and their frequencies as values
  • Each time a word appears, its count increases by 1
  • The .get() method provides a clean way to handle both new and existing words in a single line

This pattern serves as a foundation for text analysis tasks like finding common words or identifying patterns in large text datasets.

Building a memoization cache for the fibonacci() function

Dictionaries serve as efficient caching tools to dramatically speed up recursive functions by storing previously calculated results, as demonstrated in this optimized fibonacci() implementation that uses a dictionary parameter cache to remember computed Fibonacci numbers.

def fibonacci_with_cache(n, cache={}):
    if n in cache:
        return cache[n]
    if n <= 1:
        return n
    cache[n] = fibonacci_with_cache(n-1) + fibonacci_with_cache(n-2)
    return cache[n]

print(fibonacci_with_cache(10))
print(fibonacci_with_cache(20))  # Much faster with caching

This implementation of fibonacci_with_cache uses a dictionary to store previously calculated Fibonacci numbers. The function first checks if the requested number exists in the cache. If it does, it returns that value immediately instead of recalculating it.

When calculating new values, the function stores each result in the cache before returning it. This smart caching strategy prevents redundant calculations of the same Fibonacci numbers during recursive calls.

  • The default empty dictionary parameter cache={} persists between function calls
  • The base case if n <= 1: return n handles inputs 0 and 1
  • Each new calculation adds to the cache using cache[n] as the storage key

This approach transforms an exponential-time algorithm into a linear-time solution by trading memory for speed.

Common errors and challenges

Python dictionaries can trigger subtle errors when handling missing keys, mutable defaults, or iteration—understanding these challenges helps you write more reliable code.

Handling missing keys with the .get() method

Accessing a nonexistent dictionary key with square bracket notation triggers a KeyError. This common pitfall can crash your program when retrieving values that might not exist. The code below demonstrates this error when trying to access a missing email key.

user_data = {"name": "Alice", "age": 30}
email = user_data["email"]  # KeyError: 'email'
print(f"User email: {email}")

The code attempts to directly access a dictionary key that doesn't exist in user_data. When Python can't find the email key, it immediately halts execution instead of gracefully handling the missing value. Let's examine a safer approach in the code below.

user_data = {"name": "Alice", "age": 30}
email = user_data.get("email", "No email provided")
print(f"User email: {email}")

The .get() method provides a safer way to access dictionary values by accepting a default fallback value. When you request a key that doesn't exist, .get() returns the specified default instead of raising an error. This approach prevents your program from crashing when dealing with uncertain data structures.

  • Always use .get() when accessing keys that might not exist
  • Choose meaningful default values that make sense for your data type
  • Consider using .get() in data processing pipelines or when handling user input

Watch for this pattern especially when working with API responses, user-provided data, or any situation where the dictionary structure isn't guaranteed.

Avoiding mutable default parameter pitfall with dictionaries

Python's mutable default parameters can create unexpected behavior in dictionary operations. When you define a function with a dictionary as a default parameter, Python creates the dictionary only once during function definition instead of each time you call the function. The code below demonstrates this subtle trap.

def add_score(name, score, leaderboard={}):
    leaderboard[name] = score
    return leaderboard

print(add_score("Alice", 95))
print(add_score("Bob", 87))  # Still contains Alice's score!

The leaderboard dictionary persists between function calls because Python reuses the same default object. This means all function calls share and modify the same dictionary. The code below demonstrates the proper way to handle this situation.

def add_score(name, score, leaderboard=None):
    if leaderboard is None:
        leaderboard = {}
    leaderboard[name] = score
    return leaderboard

print(add_score("Alice", 95))
print(add_score("Bob", 87))  # Fresh dictionary each time

Using None as the default parameter and creating a new dictionary inside the function solves the mutable default issue. This pattern ensures each function call starts with a fresh dictionary instead of reusing the same object. The if leaderboard is None check creates a new dictionary only when needed.

  • Watch for this issue when using any mutable default parameter (lists, dictionaries, sets)
  • The problem often surfaces in caching functions or data collectors that need independent state
  • Remember that Python evaluates default arguments once during function definition

This pattern appears frequently in real-world applications that process user data or maintain separate records for different operations. Always initialize mutable defaults to None and create the actual object inside the function body.

Safely modifying dictionaries during iteration

Modifying a dictionary while iterating through it triggers a RuntimeError. Python raises this error to prevent unpredictable behavior when you add or remove items during a loop. The code below demonstrates what happens when you try to delete dictionary entries while looping through them.

data = {"a": 1, "b": 2, "c": 3, "d": 4}
for key in data:
    if data[key] % 2 == 0:  # Remove even values
        del data[key]  # RuntimeError: dictionary changed during iteration

The dictionary's size changes when del removes items. Python's iterator can't track these modifications while moving through the collection. The next code sample demonstrates a reliable approach to filter dictionary entries.

data = {"a": 1, "b": 2, "c": 3, "d": 4}
keys_to_remove = [k for k, v in data.items() if v % 2 == 0]
for key in keys_to_remove:
    del data[key]
print(data)  # {'a': 1, 'c': 3}

This solution creates a separate list of keys to remove before modifying the dictionary. The list comprehension [k for k, v in data.items() if v % 2 == 0] identifies even-valued entries first. Then a separate loop safely removes those keys from the dictionary.

  • Watch for this error when filtering dictionaries based on their values
  • The pattern applies when removing entries that match specific conditions
  • Consider using dictionary comprehension to create a new filtered dictionary instead of modifying the original

This two-step approach prevents the RuntimeError by separating the iteration from the modification. Python can safely traverse the dictionary structure when changes happen after the initial loop completes.

Learning or leveling up? Use Claude

Claude combines advanced language capabilities with deep technical expertise to serve as your personal programming companion. It excels at explaining Python concepts, reviewing code for potential improvements, and helping you implement dictionary-based solutions efficiently.

  • Dictionary basics: Ask "What's the difference between using curly braces and dict() to create dictionaries?" and Claude will explain the pros and cons of each approach with practical examples.
  • Error handling: Ask "How can I safely handle missing dictionary keys?" and Claude will demonstrate various techniques like .get() and defaultdict with clear explanations.
  • Performance tips: Ask "What's the most efficient way to merge two dictionaries?" and Claude will guide you through different methods while explaining their performance implications.
  • Code review: Ask "Can you review my dictionary implementation and suggest improvements?" and Claude will analyze your code, offering specific recommendations to enhance readability and efficiency.
  • Real-world usage: Ask "Show me how to use dictionaries for caching API responses" and Claude will provide a practical example with best practices for data storage.

Experience personalized programming guidance today by signing up for free at Claude.ai.

For a more integrated development experience, Claude Code brings AI assistance directly into your terminal, enabling seamless collaboration while you write and debug Python code.

FAQs

Additional Resources

How to return multiple values in Python

2025-05-30
14 min
 read
Read more

How to sleep in Python

2025-05-30
14 min
 read
Read more

Optimize code efficiency quickly with Claude

2025-05-30
6 min
 read
Read more

Leading companies build with Claude

ReplitCognitionGithub CopilotCursorSourcegraph
Try Claude
Get API Access
Copy
Expand