How to access a dictionary in Python

Master accessing Python dictionaries. Explore different methods, practical tips, real-world applications, and common error fixes.

How to access a dictionary in Python
Published on: 
Thu
Feb 12, 2026
Updated on: 
Mon
Apr 13, 2026
The Replit Team

Python dictionaries are a fundamental data structure for any developer. You can access their key-value pairs to manage data efficiently, a crucial skill for effective code.

In this article, you'll learn several techniques to access dictionary data. You'll find practical tips for different scenarios, explore real-world applications, and get advice to debug common issues.

Basic dictionary access with square brackets

student = {'name': 'Alice', 'age': 22, 'courses': ['Math', 'CS']}
print(student['name'])
print(student['courses'][1])--OUTPUT--Alice
CS

The most direct way to access a dictionary value is by using square brackets [] with the key. In the example, student['name'] retrieves the value 'Alice'. This method is fast and simple, but it's important to remember it will raise a KeyError if the key isn't found.

You can also chain accessors for nested data. Since the value for the 'courses' key is a list, you can immediately access its elements with another set of brackets. This is why student['courses'][1] successfully returns 'CS' from the list.

Common dictionary operations

To build on basic access and avoid potential KeyError issues, you can use more robust methods for managing and retrieving dictionary data.

Using the get() method for safer access

student = {'name': 'Alice', 'age': 22}
print(student.get('name'))
print(student.get('grade', 'Not Found')) # Provides default value if key doesn't exist--OUTPUT--Alice
Not Found

The get() method provides a forgiving way to access dictionary values, preventing the KeyError that can occur with square bracket access. It's especially useful for handling keys that might not be present in your dictionary, similar to techniques used when adding key-value pairs to dictionaries.

  • If the key exists, get() returns its value.
  • If the key is missing, it returns a default value you specify. For example, student.get('grade', 'Not Found') returns 'Not Found'.
  • If you don't provide a default and the key is missing, it simply returns None.

Accessing keys, values, and items

student = {'name': 'Alice', 'age': 22, 'major': 'Computer Science'}
print(list(student.keys()))
print(list(student.values()))
print(list(student.items()))--OUTPUT--['name', 'age', 'major']
['Alice', 22, 'Computer Science']
[('name', 'Alice'), ('age', 22), ('major', 'Computer Science')]

To work with a dictionary's contents collectively, you can use three specific methods. These methods—keys(), values(), and items()—return iterable "view objects." The example code converts these views into lists so they can be easily displayed.

  • keys() returns a view of all the keys.
  • values() returns a view of all the values.
  • items() returns a view of all key-value pairs as tuples.

Working with nested dictionaries

person = {
'name': 'Bob',
'address': {
'city': 'New York',
'zip': 10001
}
}
print(person['address']['city'])
print(f"{person['name']} lives in {person['address']['city']}")--OUTPUT--New York
Bob lives in New York

Dictionaries can hold other dictionaries as values, a technique called nesting. It's a powerful way to structure related data, like grouping an address under a single key.

  • To get to the nested data, you chain square bracket [] accessors.
  • First, person['address'] returns the inner dictionary.
  • Then, you apply the next key, ['city'], to that result to pull out the specific value.

Advanced dictionary techniques

Building on these foundational methods, you can now write more expressive and concise code for transforming and combining your dictionary data.

Dictionary comprehensions for transformation

prices = {'apple': 0.5, 'banana': 0.25, 'orange': 0.75}
doubled_prices = {fruit: price * 2 for fruit, price in prices.items()}
filtered_prices = {k: v for k, v in prices.items() if v > 0.3}
print(doubled_prices)
print(filtered_prices)--OUTPUT--{'apple': 1.0, 'banana': 0.5, 'orange': 1.5}
{'apple': 0.5, 'orange': 0.75}

Dictionary comprehensions offer a clean, one-line syntax for creating new dictionaries from existing ones. They work by iterating over an iterable, like the key-value pairs from prices.items(), and applying logic to each item. This type of concise, expressive coding aligns well with vibe coding principles.

  • You can transform data, as seen with doubled_prices, where each price is multiplied by two.
  • You can also filter data by adding an if condition. The filtered_prices example only includes items where the value is greater than 0.3.

Using defaultdict to handle missing keys

from collections import defaultdict
fruit_count = defaultdict(int)
fruits = ['apple', 'banana', 'apple', 'orange', 'banana', 'apple']
for fruit in fruits:
fruit_count[fruit] += 1
print(dict(fruit_count))--OUTPUT--{'apple': 3, 'banana': 2, 'orange': 1}

The defaultdict from Python's collections module is a handy tool for counting or grouping items. It behaves like a regular dictionary but supplies a default value for keys that don't exist yet, which helps you write cleaner code and avoid a KeyError.

  • When you initialize it with int, you're telling the dictionary to use int()—which returns 0—as the default for any new key.
  • This allows you to use an operator like += on a new key without any extra checks, since it's automatically created with a value of zero before the increment.

Merging dictionaries with the | operator

user_info = {'name': 'Charlie', 'age': 30}
additional_info = {'job': 'Developer', 'city': 'San Francisco'}
complete_info = user_info | additional_info
print(complete_info)--OUTPUT--{'name': 'Charlie', 'age': 30, 'job': 'Developer', 'city': 'San Francisco'}

The pipe | operator, introduced in Python 3.9, offers a concise way to merge two dictionaries. It creates a new dictionary by combining the key-value pairs from both operands. As you can see, user_info | additional_info results in a single dictionary containing all the data from both.

  • It’s a clean alternative to older methods like using the update() function or dictionary unpacking.
  • If there’s an overlapping key, the value from the dictionary on the right side of the operator takes precedence.

Move faster with Replit

Replit is an AI-powered development platform that comes with all Python dependencies pre-installed, so you can skip setup and start coding instantly. While mastering individual methods is key, you can use Agent 4 to go from piecing together techniques to building complete applications much faster.

Instead of just writing snippets, you can describe the app you want to build, and the Agent will take it from an idea to a working product. You can build tools that apply the very methods covered in this article:

  • A configuration manager that safely retrieves settings using get() and merges them with a default dictionary.
  • An inventory tracker that uses defaultdict to count stock levels from a stream of sales data.
  • A data transformation utility that uses a dictionary comprehension to filter and reformat a product catalog for a flash sale.

Simply describe your app, and Replit will write the code, test it, and fix issues automatically, all within your browser.

Common errors and challenges

Navigating dictionary access in Python means knowing how to sidestep a few common errors and challenges.

First, you’ll see how to gracefully handle the common KeyError, which occurs when you try to access a key that doesn't exist.

Next, you’ll learn why modifying a dictionary while looping over it can cause a RuntimeError and how to avoid this tricky situation.

Finally, understanding the difference between a dictionary reference and a true copy is crucial for preventing bugs where changes in one place unexpectedly affect another.

Handling KeyError when accessing non-existent keys

A KeyError is one of the most common issues you'll face. It happens when you try to access a dictionary key that doesn't exist using square brackets []. This immediately stops your program, so learning to handle it is essential. For comprehensive strategies on solving KeyError in Python, there are multiple prevention and handling techniques available.

The following code demonstrates what happens when you request a key that isn't in the user_data dictionary.

user_data = {'name': 'John', 'email': 'john@example.com'}
# This will raise a KeyError
phone = user_data['phone']
print(f"User's phone: {phone}")

The program crashes because it directly requests the 'phone' key, which isn't in the dictionary. The code below demonstrates a safe way to handle this situation and avoid the error.

user_data = {'name': 'John', 'email': 'john@example.com'}
# Using get() method with a default value
phone = user_data.get('phone', 'Not provided')
print(f"User's phone: {phone}")

The get() method provides a safe way to access keys that might not exist. Instead of raising a KeyError and crashing the program, it lets you provide a fallback value. This defensive programming approach is similar to code repair techniques that help maintain program stability.

  • The code successfully retrieves a default, 'Not provided', because the 'phone' key is missing.
  • This technique is essential when you're handling data from external sources, like APIs or user input, where the dictionary's structure isn't guaranteed.

Avoiding errors when modifying dictionaries during iteration

Modifying a dictionary while you're looping over it is a common pitfall that can trigger a RuntimeError. Python doesn't allow you to change the dictionary's size during iteration because it disrupts the loop's internal state. The following code demonstrates this problem.

scores = {'Alice': 85, 'Bob': 45, 'Charlie': 92, 'Dave': 38}
# This will raise RuntimeError: dictionary changed size during iteration
for name, score in scores.items():
if score < 50:
del scores[name]
print(scores)

The RuntimeError occurs because del scores[name] attempts to change the dictionary's size while the loop is still iterating over it. This action breaks the iteration process. The code below demonstrates a safe way to handle this.

scores = {'Alice': 85, 'Bob': 45, 'Charlie': 92, 'Dave': 38}
# Create a new dictionary instead of modifying during iteration
passing_scores = {name: score for name, score in scores.items() if score >= 50}
print(passing_scores)

The safe approach is to build a new dictionary instead of modifying the original one while looping. This avoids the RuntimeError entirely.

  • The solution uses a dictionary comprehension to create a new dictionary, passing_scores, containing only the items that meet the filtering condition.
  • This technique is not only safer but often more readable, especially when you need to filter data based on specific criteria without risking a program crash.

Understanding dictionary reference behavior

When you assign a dictionary to a new variable, you're not creating a copy. Instead, both variables point to the same dictionary in memory. This means a change made through one variable will unexpectedly affect the other, as the code below demonstrates.

original = {'name': 'Alice', 'scores': [85, 90, 78]}
duplicate = original # This doesn't create a new copy
duplicate['name'] = 'Bob' # Modifies both dictionaries!
print(f"Original: {original}")
print(f"Duplicate: {duplicate}")

Because duplicate is just another name for original, changing the name to 'Bob' also alters the original dictionary. The code below shows how to create a true, independent copy to prevent this from happening.

import copy
original = {'name': 'Alice', 'scores': [85, 90, 78]}
duplicate = copy.deepcopy(original) # Creates independent copy
duplicate['name'] = 'Bob' # Only modifies the duplicate
print(f"Original: {original}")
print(f"Duplicate: {duplicate}")

To prevent these unintended changes, you need a true copy. The copy.deepcopy() function creates a fully independent duplicate of the original dictionary, including any nested data. As a result, when you modify the duplicate, the original remains untouched. Understanding these reference behaviors helps avoid memory-related issues in larger applications.

  • This is crucial when you need to preserve an original dataset while creating a modified version.
  • Be especially mindful of this when your dictionary contains mutable objects like lists or other dictionaries.

Real-world applications

Beyond just avoiding errors, these dictionary techniques unlock practical solutions for complex, real-world programming challenges.

Using dictionaries for word frequency analysis

You can easily count word frequencies in a text by using a dictionary to store each word as a key and its count as the value. This demonstrates practical applications of counting words in Python using dictionary data structures.

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)
print(f"Most frequent word: {max(word_count, key=word_count.get)}")

This code efficiently tallies word occurrences. It loops through each word and uses word_count.get(word, 0) + 1 to increment its count, neatly handling new words by defaulting to zero before adding one.

  • The get() method is the key to avoiding errors, as it provides a safe way to access and update counts.
  • Finally, max() finds the most frequent word by using key=word_count.get, which tells it to compare items based on their dictionary values (the counts) rather than the keys (the words).

Building a data-driven menu system with dict as a command dispatcher

A dictionary provides a clean way to build a data-driven menu system by mapping command strings directly to the functions they should run.

def show_help():
return "Displaying help information"

def process_order():
return "Processing your order"

commands = {
'help': show_help,
'order': process_order
}

user_input = 'help'
result = commands.get(user_input, lambda: "Invalid command")()
print(result)

This code demonstrates a powerful pattern where functions are stored as dictionary values. The commands dictionary maps string keys directly to the show_help and process_order functions, creating a flexible way to trigger actions based on input.

  • The commands.get() method looks up the function associated with user_input and immediately calls it using the trailing parentheses ().
  • If the key is not found, a default lambda function is returned and executed, providing a safe way to handle invalid commands without crashing.

Get started with Replit

Put your knowledge into practice. Just tell Replit Agent: “Build an inventory tracker from sales data,” or “Create a config loader that uses default values for missing keys.”

Replit Agent handles writing the code, fixing bugs, and even deploying your app. All you need is the initial prompt. Start building with Replit.

Build your first app today

Describe what you want to build, and Replit Agent writes the code, handles the infrastructure, and ships it live. Go from idea to real product, all in your browser.

Build your first app today

Describe what you want to build, and Replit Agent writes the code, handles the infrastructure, and ships it live. Go from idea to real product, all in your browser.