How to add values to a dictionary in Python
Learn how to add values to a Python dictionary. Explore methods, tips, real-world applications, and how to debug common errors.

Python dictionaries are essential data structures for key-value pairs. You can add new values with simple syntax, which makes them flexible for dynamic data management in your applications.
In this article, we'll cover several techniques to add values, from basic assignment to the update() method. You'll find practical tips, real-world applications, and advice to debug common errors.
Using square bracket notation to add dictionary values
person = {}
person['name'] = 'Alice'
person['age'] = 30
print(person)--OUTPUT--{'name': 'Alice', 'age': 30}
The square bracket notation [] is the most straightforward way to add a new key-value pair. When you use an assignment like person['name'] = 'Alice', Python first checks if the key 'name' exists. Since the person dictionary is initially empty, Python creates the key and assigns the specified value to it.
This syntax is powerful because it also handles updates. If a key already exists, the same operation will overwrite its current value instead of creating a duplicate entry. This dual functionality makes it a memory-efficient tool for managing dictionary data, whether you're adding new information or modifying what's already there. For more details on accessing dictionary values, see our comprehensive guide.
Basic dictionary operations
Adding single values is just the start, as Python also provides specialized tools like the update() method, the ** operator, and setdefault() for more advanced operations.
Adding multiple values with the update() method
person = {'name': 'Alice'}
person.update({'age': 30, 'city': 'New York'})
print(person)--OUTPUT--{'name': 'Alice', 'age': 30, 'city': 'New York'}
The update() method is your go-to for adding multiple key-value pairs in one shot. You pass it another dictionary, and its items are merged into the original, making it a clean way to perform bulk additions.
- If a key from the new dictionary already exists, its value is overwritten.
- This behavior is useful for both adding new data and modifying existing entries simultaneously.
Merging dictionaries with the ** operator
person = {'name': 'Alice'}
additional_info = {'age': 30, 'city': 'New York'}
updated_person = {**person, **additional_info}
print(updated_person)--OUTPUT--{'name': 'Alice', 'age': 30, 'city': 'New York'}
The double-asterisk ** operator offers a clean and modern syntax for merging dictionaries. It works by "unpacking" the key-value pairs from existing dictionaries into a new one. This approach is often favored for its readability, especially when combining multiple sources of data.
- This operation creates a brand-new dictionary, leaving the original ones untouched—a key difference from the in-place
update()method. - If both dictionaries happen to share a key, the value from the rightmost dictionary will overwrite the other in the final result.
For more comprehensive techniques on merging two dictionaries in Python, explore additional methods and best practices.
Conditionally adding values with setdefault()
person = {'name': 'Alice'}
person.setdefault('age', 30) # Sets 'age' only if it doesn't exist
person.setdefault('name', 'Bob') # Won't change existing 'name'
print(person)--OUTPUT--{'name': 'Alice', 'age': 30}
The setdefault() method offers a safe way to add a key-value pair without overwriting existing data. It checks if a key is present; if not, it adds the key with a specified default value. If the key already exists, the method does nothing and leaves the original value untouched.
- In the example,
person.setdefault('age', 30)adds the new key because'age'isn't in the dictionary. - However,
person.setdefault('name', 'Bob')has no effect since'name'already exists with the value'Alice'.
Advanced dictionary operations
Moving beyond the fundamentals, Python offers powerful constructs like dictionary comprehensions and specialized classes from the collections module for advanced data management.
Creating and updating dictionaries with dictionary comprehensions
person = {'name': 'Alice'}
new_data = [('age', 30), ('city', 'New York'), ('job', 'Engineer')]
updated_person = {**person, **{k: v for k, v in new_data}}
print(updated_person)--OUTPUT--{'name': 'Alice', 'age': 30, 'city': 'New York', 'job': 'Engineer'}
Dictionary comprehensions offer a compact and readable way to create dictionaries from iterables. In this case, the comprehension {k: v for k, v in new_data} dynamically builds a dictionary from a list of key-value tuples.
- This new dictionary is then merged with the original
persondictionary using the**operator, which unpacks both into a single expression. - This technique is powerful because it allows you to construct and combine dictionaries in one clean, expressive line of code, creating an updated copy without altering the original sources. When working with dictionary copies, understanding different approaches to copying dictionaries can help you choose the right method.
Automatic initialization with collections.defaultdict
from collections import defaultdict
skills = defaultdict(list)
skills['Alice'].append('Python')
skills['Alice'].append('SQL')
skills['Bob'].append('JavaScript')
print(dict(skills))--OUTPUT--{'Alice': ['Python', 'SQL'], 'Bob': ['JavaScript']}
The defaultdict from the collections module is a lifesaver when you're grouping items. By initializing it with defaultdict(list), you tell the dictionary to automatically create an empty list for any new key you access. This streamlines your code by letting you call methods like .append() directly without manual checks.
- It completely avoids the common
KeyErroryou'd get with a regular dictionary when a key is missing. - This makes your logic for aggregating data—like collecting skills for each person—much cleaner and more direct.
Combining dictionaries with collections.ChainMap
from collections import ChainMap
person = {'name': 'Alice'}
additional_info = {'age': 30, 'city': 'New York'}
combined = ChainMap(person, additional_info)
print(dict(combined))--OUTPUT--{'name': 'Alice', 'age': 30, 'city': 'New York'}
The collections.ChainMap provides a clever way to group multiple dictionaries into a single, searchable view. It doesn't actually merge them; instead, it creates a live link between the original dictionaries, treating them as one logical unit.
- Lookups search the dictionaries sequentially—from first to last—and return the first value found for a given key.
- Crucially, any updates or new additions only modify the very first dictionary in the chain, leaving the others untouched.
Move faster with Replit
Replit is an AI-powered development platform where all Python dependencies are pre-installed, so you can skip setup and start coding instantly. This lets you move from learning individual techniques to building complete applications with Agent 4, which handles everything from code and databases to deployment.
Instead of just piecing together methods like update() or setdefault(), you can describe the full application you want to build. Agent 4 will take it from idea to working product:
- A configuration tool that merges a base settings dictionary with user-defined overrides using the
**operator. - A data aggregator that uses
defaultdictto group records, like organizing sales data by region from a raw list. - A user profile builder that safely adds new information with
setdefault()to ensure default values are applied without overwriting existing data.
Simply describe your app, and Replit will write the code, test it, and fix issues automatically, all within your browser.
Common errors and challenges
While adding values is usually simple, you can run into a few common pitfalls that are easy to avoid with the right techniques.
A KeyError is one of the most frequent issues, occurring when you try to access a key that doesn't exist. To prevent your code from crashing, you have a few options:
- Use the
.get()method, which returnsNoneor a specified default value if a key is missing. - Check for a key's existence with the
inkeyword (e.g.,if 'key' in my_dict:) before attempting to access it.
Modifying a dictionary while looping over it will trigger a RuntimeError because Python can't track changes to a collection's size during iteration. The solution is to iterate over a copy. By creating a list from the dictionary's keys or items, such as for key in list(my_dict):, you can safely add or remove entries from the original dictionary within the loop.
Nested dictionaries can also be tricky. Accessing a deep key like data['user']['profile'] will fail if an intermediate key like 'user' doesn't exist. You can safely navigate the structure by chaining .get() calls, like data.get('user', {}).get('profile'). This approach returns None instead of an error if any part of the chain is missing.
Avoiding KeyError when accessing non-existent keys
A KeyError is a frequent roadblock that stops your code cold. It’s triggered when you ask for a key that isn't in the dictionary. The following code demonstrates this by trying to access the non-existent 'email' key.
user_data = {'name': 'Alice', 'age': 30}
email = user_data['email']
print(f"User email: {email}")
This direct access with user_data['email'] fails because the key isn't defined, immediately triggering a KeyError. The following code demonstrates a safer way to retrieve values that might be missing, preventing the program from crashing.
user_data = {'name': 'Alice', 'age': 30}
email = user_data.get('email', 'No email provided')
print(f"User email: {email}")
The get() method is a safe alternative to square brackets for accessing keys. It looks for 'email', and since it's not found, it returns the default value 'No email provided' instead of raising a KeyError. This approach is ideal when dealing with data where some keys are optional, such as API responses or user-submitted forms, ensuring your application remains stable even with incomplete information.
Avoiding errors when modifying dictionaries during iteration
Modifying a dictionary while you're looping over it is a classic Python pitfall. It triggers a RuntimeError because the dictionary's size changes mid-iteration, which confuses the loop. The code below shows what happens when you try to add a new key.
data = {'a': 1, 'b': 2, 'c': 3}
for key in data:
if key == 'a':
data['d'] = 4
print(data)
The for loop iterates directly over data. When the code adds a new key with data['d'] = 4, it alters the dictionary during iteration, triggering the error. The following example shows how to do this correctly.
data = {'a': 1, 'b': 2, 'c': 3}
for key in list(data.keys()):
if key == 'a':
data['d'] = 4
print(data)
The fix is to iterate over a static copy of the dictionary’s keys. By creating a list with list(data.keys()), you’re working with a separate, unchanging collection. This lets you safely modify the original data dictionary inside the loop without triggering a RuntimeError. This approach is crucial whenever your loop’s logic needs to add or remove items from the same dictionary you are iterating through, such as when cleaning or enriching data on the fly.
Handling errors with missing nested dictionary keys
Nested dictionaries are great for organizing complex data, but they introduce a new challenge. Accessing a key deep within the structure will fail if any intermediate key is missing, triggering a KeyError. The following code demonstrates this exact problem.
user_profiles = {
'alice': {'name': 'Alice'},
'bob': {'name': 'Bob', 'settings': {'theme': 'dark'}}
}
alice_theme = user_profiles['alice']['settings']['theme']
print(f"Alice's theme: {alice_theme}")
The attempt to access user_profiles['alice']['settings'] fails because the 'settings' key is missing, which triggers a KeyError. The code below demonstrates how to safely retrieve nested values without causing your program to crash.
user_profiles = {
'alice': {'name': 'Alice'},
'bob': {'name': 'Bob', 'settings': {'theme': 'dark'}}
}
alice = user_profiles.get('alice', {})
settings = alice.get('settings', {})
alice_theme = settings.get('theme', 'default')
print(f"Alice's theme: {alice_theme}")
The solution is to chain .get() calls, which safely navigates the nested structure. Each call attempts to retrieve a key; if it's missing, it returns a default value (like an empty dictionary {}) instead of raising an error. This lets the next .get() in the chain continue safely. This technique is essential when parsing data with optional fields, such as API responses, ensuring your code doesn't crash on incomplete information.
Real-world applications
Beyond the syntax, these dictionary methods are essential for building practical features, from managing user settings to analyzing text data.
Managing user preferences with dictionary updates
In many applications, dictionaries are used to manage user settings by merging a default configuration with a user's specific choices, ensuring every option has a defined value.
user_defaults = {'theme': 'light', 'notifications': True, 'language': 'en'}
user_preferences = {}
user_preferences.update({'theme': 'dark'})
active_settings = {**user_defaults, **user_preferences}
print(active_settings)
This code combines two previously discussed methods to merge dictionaries:
- First, an empty dictionary is populated using the
update()method to createuser_preferences. - Next, the
**operator unpacks bothuser_defaultsanduser_preferencesinto a new dictionary.
Because the 'theme' key exists in both source dictionaries, the value from the rightmost one—user_preferences—takes precedence. This sets the final value for 'theme' in active_settings to 'dark'.
Creating a word frequency counter with defaultdict
A defaultdict is perfect for tallying items, like counting word frequencies in a block of text, because it automatically initializes new keys with a default value of zero.
When you create word_count = defaultdict(int), you're telling Python that if a key doesn't exist, it should be created with a value of 0. This makes the line word_count[word] += 1 incredibly efficient. You can increment the count for any word without first checking if it's already in the dictionary.
- This completely removes the need for boilerplate code like
if word in word_count:, resulting in cleaner and more readable logic for aggregation tasks.
The final dictionary shows the frequency of each word, and a simple list comprehension can then filter for the most common ones.
from collections import defaultdict
text = "to be or not to be that is the question"
word_count = defaultdict(int)
for word in text.split():
word_count[word] += 1
print(dict(word_count))
print("Most frequent words:", [w for w, c in word_count.items() if c > 1])
This code efficiently counts word occurrences in a string. It iterates through each word from text.split() and uses a defaultdict to increment a counter for that word. Text analysis tasks like this showcase why AI coding with Python is so effective for data processing applications. For more comprehensive approaches to counting words in Python, explore different techniques and optimization strategies.
- The
word_count[word] += 1operation is the core of the tallying logic. - After counting, a list comprehension filters the results. It iterates over the dictionary's key-value pairs,
word_count.items(), and builds a new list containing only the words whose count is greater than one. This provides a concise way to identify repeated words.
Get started with Replit
Now, turn what you've learned into a real tool. Give Replit Agent a prompt like "build a config manager that merges default and user settings" or "create a tool that counts word frequency using defaultdict".
The Agent writes the code, tests for errors, and deploys the application for you. It handles the complex parts so you can focus on the idea. Start building with Replit.
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.
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.



