Dictionaries
Python Dictionaries: Explanation with Examples
A dictionary in Python is an unordered collection of items that stores data in key-value pairs. Dictionaries are:
- Mutable (can be changed after creation)
- Indexed by keys (not by numbers like lists)
- Enclosed in curly braces
{} - Also known as “associative arrays” or “hash maps” in other languages
Creating a Dictionary
python
# Empty dictionary
my_dict = {}
# Dictionary with initial values
student = {
"name": "John Doe",
"age": 21,
"courses": ["Math", "Physics", "Chemistry"],
"GPA": 3.7
}
Accessing Dictionary Elements
python
print(student["name"]) # Output: John Doe
print(student.get("age")) # Output: 21
# Using get() prevents KeyError if key doesn't exist
print(student.get("address")) # Output: None
print(student.get("address", "Not Found")) # Output: Not Found
Modifying a Dictionary
python
# Adding/Updating elements
student["age"] = 22 # Update existing key
student["university"] = "Harvard" # Add new key-value pair
# Update multiple items at once
student.update({
"age": 23,
"phone": "555-1234",
"email": "john@example.com"
})
Dictionary Operations
python
# Check if key exists
if "GPA" in student:
print(f"GPA: {student['GPA']}")
# Length of dictionary
print(len(student)) # Output: 7 (number of key-value pairs)
# Remove elements
del student["phone"] # Removes the key-value pair
age = student.pop("age") # Removes and returns the value
Iterating Through a Dictionary
python
# Print all keys
for key in student:
print(key)
# Print all key-value pairs
for key, value in student.items():
print(f"{key}: {value}")
# Print all values
for value in student.values():
print(value)
Dictionary Methods
python
# Create a copy student_copy = student.copy() # Clear all items student_copy.clear() # Get all keys or values keys = student.keys() values = student.values()
Practical Example
python
# Phone book example
phone_book = {
"Alice": "555-1234",
"Bob": "555-5678",
"Charlie": "555-9012"
}
# Add a new contact
phone_book["David"] = "555-3456"
# Update Bob's number
phone_book["Bob"] = "555-0000"
# Remove Charlie
phone_book.pop("Charlie")
# Search for a number
name = "Alice"
if name in phone_book:
print(f"{name}'s number: {phone_book[name]}")
else:
print(f"{name} not found in phone book")
Dictionaries are extremely useful when you need to store and retrieve data using meaningful keys rather than numerical indices. They provide fast lookups and are optimized for retrieving values when the key is known.
Dictionary Creation Methods in Python
Python provides several ways to create dictionaries. Here are the main methods with examples for each:
1. Using Curly Braces {} (Most Common)
The simplest way to create a dictionary by enclosing key-value pairs in curly braces.
python
# Empty dictionary
empty_dict = {}
# Dictionary with string keys
person = {"name": "Alice", "age": 25, "city": "New York"}
# Dictionary with mixed key types
mixed_keys = {1: "one", "two": 2, 3.0: "three"}
# Nested dictionary
employees = {
"manager": {"name": "John", "age": 40},
"developer": {"name": "Sarah", "age": 32}
}
2. Using the dict() Constructor
The dict() function can create dictionaries in different ways.
python
# From keyword arguments
dict1 = dict(name="Bob", age=30, job="developer")
# From list of tuples
dict2 = dict([("a", 1), ("b", 2), ("c", 3)])
# From two parallel lists (using zip)
keys = ["x", "y", "z"]
values = [10, 20, 30]
dict3 = dict(zip(keys, values))
# Empty dictionary
dict4 = dict()
3. Dictionary Comprehension
Similar to list comprehensions but for creating dictionaries.
python
# Squares of numbers
squares = {x: x*x for x in range(1, 5)}
# Result: {1: 1, 2: 4, 3: 9, 4: 16}
# Uppercase letters mapping
letters = {chr(i): i for i in range(65, 70)}
# Result: {'A': 65, 'B': 66, 'C': 67, 'D': 68, 'E': 69}
# Conditional comprehension
even_odd = {x: "even" if x%2 == 0 else "odd" for x in range(1, 6)}
# Result: {1: 'odd', 2: 'even', 3: 'odd', 4: 'even', 5: 'odd'}
# Nested dictionary comprehension
matrix = {i: {j: i*j for j in range(1, 4)} for i in range(1, 4)}
# Result: {1: {1: 1, 2: 2, 3: 3}, 2: {1: 2, 2: 4, 3: 6}, 3: {1: 3, 2: 6, 3: 9}}
4. Using fromkeys() Method
Creates a new dictionary with keys from a sequence and all values set to a default.
python
# All values set to None
keys = ["a", "b", "c"]
dict1 = dict.fromkeys(keys)
# Result: {'a': None, 'b': None, 'c': None}
# All values set to default value
dict2 = dict.fromkeys(["name", "age", "city"], "unknown")
# Result: {'name': 'unknown', 'age': 'unknown', 'city': 'unknown'}
# Using range as keys
dict3 = dict.fromkeys(range(1, 4), 0)
# Result: {1: 0, 2: 0, 3: 0}
# With mutable default value (be careful with this)
dict4 = dict.fromkeys(["a", "b", "c"], [])
dict4["a"].append(1) # Affects all values
# Result: {'a': [1], 'b': [1], 'c': [1]}
Each creation method has its own use cases:
- Curly braces
{}are best for static dictionaries dict()constructor is useful when converting other data structures- Dictionary comprehensions are great for dynamic creation
fromkeys()is perfect for initializing dictionaries with default values
different ways to create dictionaries using iterable pairs, zip(), and enumerate() functions in Python, each explained with examples:
1. Using Iterable Pairs (List of Tuples/List of Lists)
You can create a dictionary from an iterable containing key-value pairs (tuples or lists).
Examples:
python
# From a list of tuples
pairs_tuples = [("name", "Alice"), ("age", 25), ("city", "Paris")]
dict1 = dict(pairs_tuples)
print(dict1) # Output: {'name': 'Alice', 'age': 25, 'city': 'Paris'}
# From a list of lists
pairs_lists = [["a", 1], ["b", 2], ["c", 3]]
dict2 = dict(pairs_lists)
print(dict2) # Output: {'a': 1, 'b': 2, 'c': 3}
# From a tuple of tuples
pairs_nested = (("x", 10), ("y", 20), ("z", 30))
dict3 = dict(pairs_nested)
print(dict3) # Output: {'x': 10, 'y': 20, 'z': 30}
# From a set of tuples (unordered)
pairs_set = {("key1", 100), ("key2", 200)}
dict4 = dict(pairs_set)
print(dict4) # Output: {'key1': 100, 'key2': 200} (order may vary)
2. Using zip() to Combine Two Iterables
zip() pairs elements from two iterables (lists, tuples, etc.) into key-value pairs.
Examples:
python
# From two lists (keys and values)
keys = ["name", "age", "country"]
values = ["Bob", 30, "USA"]
dict1 = dict(zip(keys, values))
print(dict1) # Output: {'name': 'Bob', 'age': 30, 'country': 'USA'}
# From two tuples
keys_tuple = ("a", "b", "c")
values_tuple = (1, 2, 3)
dict2 = dict(zip(keys_tuple, values_tuple))
print(dict2) # Output: {'a': 1, 'b': 2, 'c': 3}
# Unequal length iterables (uses shortest length)
short_keys = ["x", "y"]
long_values = [10, 20, 30]
dict3 = dict(zip(short_keys, long_values))
print(dict3) # Output: {'x': 10, 'y': 20} (30 is ignored)
# Using range() for keys
values = ["apple", "banana", "cherry"]
dict4 = dict(zip(range(1, 4), values))
print(dict4) # Output: {1: 'apple', 2: 'banana', 3: 'cherry'}
3. Using enumerate() to Auto-Generate Keys
enumerate() assigns numeric keys (indices) to values in an iterable.
Examples:
python
# List to dictionary with index as keys
fruits = ["apple", "banana", "cherry"]
dict1 = dict(enumerate(fruits))
print(dict1) # Output: {0: 'apple', 1: 'banana', 2: 'cherry'}
# Start index at 1 instead of 0
dict2 = dict(enumerate(fruits, start=1))
print(dict2) # Output: {1: 'apple', 2: 'banana', 3: 'cherry'}
# With strings (keys = positions, values = characters)
word = "hello"
dict3 = dict(enumerate(word))
print(dict3) # Output: {0: 'h', 1: 'e', 2: 'l', 3: 'l', 4: 'o'}
# Using enumerate with zip for complex keys
names = ["Alice", "Bob", "Charlie"]
ages = [25, 30, 35]
dict4 = {i: (name, age) for i, (name, age) in enumerate(zip(names, ages))}
print(dict4) # Output: {0: ('Alice', 25), 1: ('Bob', 30), 2: ('Charlie', 35)}
Comparison Table
| Method | Use Case | Example |
|---|---|---|
| Iterable Pairs | When you have a list of (key, value) pairs | dict([("a", 1), ("b", 2)]) |
zip() | When keys and values are in separate lists | dict(zip(keys_list, values_list)) |
enumerate() | When you want auto-incremented keys | dict(enumerate(["a", "b", "c"])) |
Looping Over Dictionaries and Using the get() Method in Python
Looping Over Dictionaries
Python provides several ways to iterate through dictionaries:
1. Looping Through Keys (Default Behavior)
python
my_dict = {'name': 'Alice', 'age': 25, 'city': 'New York'}
# Default loop gives keys
for key in my_dict:
print(key)
# Output:
# name
# age
# city
# Equivalent to:
for key in my_dict.keys():
print(key)
2. Looping Through Values
python
for value in my_dict.values():
print(value)
# Output:
# Alice
# 25
# New York
3. Looping Through Key-Value Pairs
python
for key, value in my_dict.items():
print(f"{key}: {value}")
# Output:
# name: Alice
# age: 25
# city: New York
4. Looping with Index (Using enumerate)
python
for i, (key, value) in enumerate(my_dict.items()):
print(f"{i}. {key} = {value}")
# Output:
# 0. name = Alice
# 1. age = 25
# 2. city = New York
The get() Method
The get() method is a safe way to access dictionary values that prevents KeyError exceptions.
Basic Usage
python
value = my_dict.get('name')
print(value) # Output: Alice
value = my_dict.get('address')
print(value) # Output: None (instead of raising KeyError)
With Default Value
python
# Return 'Unknown' if key doesn't exist
age = my_dict.get('age', 'Unknown')
print(age) # Output: 25 (exists)
phone = my_dict.get('phone', 'Unknown')
print(phone) # Output: Unknown (key doesn't exist)
Practical Examples
- Counting with Dictionaries
python
fruits = ['apple', 'banana', 'apple', 'orange', 'banana', 'apple']
count = {}
for fruit in fruits:
count[fruit] = count.get(fruit, 0) + 1
print(count)
# Output: {'apple': 3, 'banana': 2, 'orange': 1}
- Nested Dictionary Access
python
users = {
'alice': {'age': 25, 'email': 'alice@example.com'},
'bob': {'age': 30}
}
# Safe access to nested data
print(users.get('alice', {}).get('email', 'No email'))
# Output: alice@example.com
print(users.get('bob', {}).get('email', 'No email'))
# Output: No email
print(users.get('charlie', {}).get('email', 'No email'))
# Output: No email
- Configuration with Defaults
python
config = {'theme': 'dark', 'language': 'en'}
# Get settings with defaults
theme = config.get('theme', 'light')
notifications = config.get('notifications', True)
print(theme) # Output: dark (from config)
print(notifications) # Output: True (default)
Key Differences: dict[key] vs dict.get(key)
| Feature | dict[key] | dict.get(key) |
|---|---|---|
| Key exists | Returns value | Returns value |
| Key missing | Raises KeyError | Returns None (or default) |
| Use case | When you’re sure key exists | When key might be missing |
The get() method is particularly useful when:
- You’re not sure if a key exists
- You want to provide a default value
- You’re working with nested dictionaries
- You want to avoid try/except blocks for missing keys
Understanding setdefault() in Python Dictionaries
The setdefault() method is a powerful dictionary operation that combines getting a value and setting a default if the key doesn’t exist. It’s particularly useful for working with nested dictionaries and counting operations.
Basic Syntax
python
dict.setdefault(key, default_value)
- If
keyexists: returns its current value (ignoresdefault_value) - If
keydoesn’t exist: setskeytodefault_valueand returnsdefault_value
Key Use Cases
1. Initializing Missing Keys
python
employee = {'name': 'Alice', 'age': 30}
# Get department or set default
department = employee.setdefault('department', 'Engineering')
print(department) # Output: 'Engineering'
print(employee) # Output: {'name': 'Alice', 'age': 30, 'department': 'Engineering'}
# Key exists - returns current value without changing
age = employee.setdefault('age', 25)
print(age) # Output: 30 (original value preserved)
2. Working with Nested Dictionaries
python
data = {}
person = 'Alice'
# Without setdefault (verbose way)
if person not in data:
data[person] = []
data[person].append('Python')
# With setdefault (cleaner way)
data.setdefault('Bob', []).append('Java')
print(data)
# Output: {'Alice': ['Python'], 'Bob': ['Java']}
3. Counting Occurrences
python
fruits = ['apple', 'banana', 'apple', 'orange', 'banana', 'apple']
count = {}
for fruit in fruits:
count.setdefault(fruit, 0)
count[fruit] += 1
print(count)
# Output: {'apple': 3, 'banana': 2, 'orange': 1}
4. Grouping Items
python
people = [
{'name': 'Alice', 'department': 'Engineering'},
{'name': 'Bob', 'department': 'Marketing'},
{'name': 'Charlie', 'department': 'Engineering'}
]
dept_groups = {}
for person in people:
dept_groups.setdefault(person['department'], []).append(person['name'])
print(dept_groups)
# Output: {'Engineering': ['Alice', 'Charlie'], 'Marketing': ['Bob']}
Comparison with get()
| Method | Returns | Modifies Dictionary | Typical Use Case |
|---|---|---|---|
get(key, default) | Value or default | No | Safe value retrieval |
setdefault(key, default) | Value or default | Yes (if key missing) | Initialize missing keys |
Common Pitfalls
- Mutable Defaults: Be careful with mutable default valuespython# This creates the SAME list for all missing keys! data = {} data.setdefault(‘a’, []).append(1) data.setdefault(‘b’, []).append(2) print(data) # Might surprise you: {‘a’: [1, 2], ‘b’: [1, 2]} # Better alternative: from collections import defaultdict data = defaultdict(list)
- Performance:
setdefault()is slightly slower than checking first if you don’t need the return value
When to Use setdefault()
- When you need to both check for a key’s existence AND potentially set a default
- When working with nested dictionary structures
- When initializing dictionary values that are containers (lists, sets, etc.)
- When you want to write more concise dictionary initialization code
Alternatives
For more complex cases, consider:
collections.defaultdict- Dictionary comprehensions
- The
|merge operator (Python 3.9+)
Comprehensive Guide to Python Dictionary Methods
Dictionaries in Python come with a variety of built-in methods that make working with key-value pairs efficient and convenient. Here’s a complete reference to all dictionary methods with examples:
1. Core Dictionary Methods
clear()
Removes all items from the dictionary.
python
d = {'a': 1, 'b': 2}
d.clear()
print(d) # {}
copy()
Returns a shallow copy of the dictionary.
python
original = {'x': 1, 'y': 2}
new_dict = original.copy()
new_dict['x'] = 10
print(original) # {'x': 1, 'y': 2}
print(new_dict) # {'x': 10, 'y': 2}
get(key[, default])
Returns the value for key if it exists, otherwise returns default (None if not specified).
python
d = {'name': 'Alice', 'age': 30}
print(d.get('name')) # Alice
print(d.get('address')) # None
print(d.get('phone', 'N/A')) # N/A
items()
Returns a view object of (key, value) pairs.
python
d = {'a': 1, 'b': 2}
for k, v in d.items():
print(f"{k}: {v}")
# Output:
# a: 1
# b: 2
keys()
Returns a view object of dictionary keys.
python
d = {'x': 10, 'y': 20}
print(d.keys()) # dict_keys(['x', 'y'])
values()
Returns a view object of dictionary values.
python
d = {'a': 100, 'b': 200}
print(d.values()) # dict_values([100, 200])
2. Modification Methods
pop(key[, default])
Removes and returns the value for key. Raises KeyError if key not found and default not provided.
python
d = {'a': 1, 'b': 2}
val = d.pop('a')
print(val) # 1
print(d) # {'b': 2}
# With default
val = d.pop('c', 'Not found')
print(val) # Not found
popitem()
Removes and returns the last inserted (key, value) pair as a tuple.
python
d = {'x': 10, 'y': 20}
item = d.popitem()
print(item) # ('y', 20)
print(d) # {'x': 10}
update([other])
Updates dictionary with key/value pairs from other, overwriting existing keys.
python
d = {'a': 1, 'b': 2}
d.update({'b': 3, 'c': 4})
print(d) # {'a': 1, 'b': 3, 'c': 4}
# Also works with keyword args
d.update(d=5, e=6)
print(d) # {'a': 1, 'b': 3, 'c': 4, 'd': 5, 'e': 6}
setdefault(key[, default])
Returns value of key if exists, else inserts key with default value and returns default.
python
d = {'name': 'Alice'}
age = d.setdefault('age', 30)
print(age) # 30
print(d) # {'name': 'Alice', 'age': 30}
3. Dictionary View Objects
Dictionary methods keys(), values(), and items() return view objects that provide dynamic views of dictionary entries.
python
d = {'a': 1, 'b': 2}
keys = d.keys()
values = d.values()
items = d.items()
d['c'] = 3 # Modifying the dictionary
print(list(keys)) # ['a', 'b', 'c']
print(list(values)) # [1, 2, 3]
print(list(items)) # [('a', 1), ('b', 2), ('c', 3)]
4. Dictionary Comprehension
While not a method, dictionary comprehensions are a powerful way to create dictionaries:
python
# Create dictionary from list
numbers = [1, 2, 3]
squared = {x: x**2 for x in numbers}
print(squared) # {1: 1, 2: 4, 3: 9}
# Filter dictionary
original = {'a': 1, 'b': 2, 'c': 3}
filtered = {k: v for k, v in original.items() if v > 1}
print(filtered) # {'b': 2, 'c': 3}
5. Special Methods
fromkeys(iterable[, value])
Class method that creates a new dictionary with keys from iterable and values set to value.
python
keys = ['a', 'b', 'c']
d = dict.fromkeys(keys, 0)
print(d) # {'a': 0, 'b': 0, 'c': 0}
# Without value parameter
d = dict.fromkeys(keys)
print(d) # {'a': None, 'b': None, 'c': None}
__missing__ (for subclassing)
Called when getitem() can’t find the key (used when subclassing dict).
python
class DefaultDict(dict):
def __missing__(self, key):
return 'default'
d = DefaultDict({'a': 1})
print(d['a']) # 1
print(d['b']) # 'default'
Practical Examples
Counting word frequencies
python
text = "apple banana apple orange banana apple"
words = text.split()
count = {}
for word in words:
count[word] = count.get(word, 0) + 1
print(count) # {'apple': 3, 'banana': 2, 'orange': 1}
Inverting a dictionary
python
original = {'a': 1, 'b': 2, 'c': 1}
inverted = {}
for key, value in original.items():
inverted.setdefault(value, []).append(key)
print(inverted) # {1: ['a', 'c'], 2: ['b']}
Merging dictionaries (Python 3.9+)
python
dict1 = {'a': 1, 'b': 2}
dict2 = {'b': 3, 'c': 4}
# New in Python 3.9
merged = dict1 | dict2
print(merged) # {'a': 1, 'b': 3, 'c': 4}
# Update in-place
dict1 |= dict2
print(dict1) # {'a': 1, 'b': 3, 'c': 4}
These methods provide comprehensive functionality for working with dictionaries in Python, making them one of the most versatile and frequently used data structures in the language.