Post

06. Python Dictionaries

πŸ”‘ Unlock the power of Python Dictionaries! This guide dives deep into dictionary manipulation, methods, comprehensions, and best practices, equipping you with the skills to efficiently manage and utilize key-value pairs in your Python projects. πŸš€

06. Python Dictionaries

What we will learn in this post?

  • πŸ‘‰ Introduction to Python Dictionaries
  • πŸ‘‰ Accessing and Modifying Dictionary Elements
  • πŸ‘‰ Dictionary Methods - Part 1
  • πŸ‘‰ Dictionary Methods - Part 2
  • πŸ‘‰ Dictionary Comprehensions
  • πŸ‘‰ Nested Dictionaries
  • πŸ‘‰ Dictionary Operations and Best Practices
  • πŸ‘‰ Conclusion!

Dictionaries: Key-Value Powerhouses πŸ”‘

Dictionaries in Python are like super-organized address books! They store information in key-value pairs. Think of it this way:

  • The key is like the person’s name.
  • The value is their address.
graph LR
    A[Key] --> B(Value)

What Makes Dictionaries Special?

  • Dictionaries are mutable, meaning you can change them after they’re created.
  • From Python 3.7 onwards, dictionaries remember the order in which you added items (insertion-ordered), and this is helpful when we have a need to remember the order.
  • You create them using curly braces {}.
1
2
3
# Creating a dictionary
my_dict = {"name": "Alice", "age": 30, "city": "New York"}
print(my_dict) # Output: {'name': 'Alice', 'age': 30, 'city': 'New York'}

Dictionary Use Cases πŸ’‘

Dictionaries are useful for:

  • Storing configuration settings.
  • Representing objects with named properties.
  • Counting frequencies of items, for example, how many times we encounter a word.

Resources: Python Dictionaries Documentation

Dictionary Fun: Accessing, Modifying, & More! πŸ“š

Let’s explore how to work with dictionaries in Python! They’re like real-world dictionaries, pairing keys with values. πŸ—οΈ

Accessing Values with Keys πŸ”‘

You grab a value by using its key inside square brackets: my_dictionary['key']. If the key doesn’t exist, you’ll get a KeyError. Use the .get() method to avoid this! It returns None (or a default value you specify) if the key is missing.

1
2
3
4
my_dict = {'name': 'Alice', 'age': 30}
print(my_dict['name']) # Output: Alice
print(my_dict.get('city')) # Output: None
print(my_dict.get('city', 'Unknown')) # Output: Unknown

Modifying and Adding βœοΈβž•

Change a value by assigning a new one to its key: my_dictionary['key'] = new_value. To add a completely new key-value pair, simply assign a value to a new key: my_dictionary['new_key'] = value.

1
2
3
my_dict['age'] = 31  # Modifying
my_dict['city'] = 'New York' # Adding
print(my_dict) # Output: {'name': 'Alice', 'age': 31, 'city': 'New York'}

Deleting Items πŸ—‘οΈ

Use the del keyword followed by the dictionary and the key in square brackets: del my_dictionary['key'].

1
2
del my_dict['age']
print(my_dict) # Output: {'name': 'Alice', 'city': 'New York'}
graph LR
    D_START["Dictionary"]:::javaStyle --> D_ACCESS["Access Value"]:::jdbcStyle
    D_START --> D_ADD["Add Key-Value"]:::driverStyle
    D_START --> D_DEL["Delete Key"]:::dbStyle
    D_ACCESS --> D_RESULT["Get Value"]:::useStyle
    D_ADD --> D_RESULT
    D_DEL --> D_RESULT

    classDef javaStyle fill:#ff4f81,stroke:#c43e3e,color:#fff,font-size:16px,stroke-width:3px,rx:14,shadow:6px;
    classDef jdbcStyle fill:#6b5bff,stroke:#4a3f6b,color:#fff,font-size:16px,stroke-width:3px,rx:14,shadow:6px;
    classDef driverStyle fill:#ffd700,stroke:#d99120,color:#222,font-size:16px,stroke-width:3px,rx:14,shadow:6px;
    classDef dbStyle fill:#00bfae,stroke:#005f99,color:#fff,font-size:16px,stroke-width:3px,rx:14,shadow:6px;
    classDef useStyle fill:#ff9800,stroke:#f57c00,color:#fff,font-size:16px,stroke-width:3px,rx:14,shadow:6px;

    class D_START javaStyle;
    class D_ACCESS jdbcStyle;
    class D_ADD driverStyle;
    class D_DEL dbStyle;
    class D_RESULT useStyle;

    linkStyle default stroke:#e67e22,stroke-width:3px;

For more in-depth learning check out these resources!

Dictionary Methods: Your Dictionary Toolkit! 🧰

Dictionaries in Python are like treasure chests πŸ’°, holding key-value pairs. Let’s explore some useful tools to manage them!

Accessing Dictionary Data

keys(): Unlocking the Keys

The .keys() method gives you a view object containing all the keys in your dictionary.

1
2
3
my_dict = {"name": "Alice", "age": 30, "city": "New York"}
keys = my_dict.keys()
print(keys) # Output: dict_keys(['name', 'age', 'city'])

values(): Revealing the Values

Similar to .keys(), .values() provides a view object containing all the values.

1
2
values = my_dict.values()
print(values) # Output: dict_values(['Alice', 30, 'New York'])

items(): Getting Key-Value Pairs

.items() returns a view object with key-value pairs as tuples. Super handy for looping!

1
2
3
4
5
6
7
8
9
items = my_dict.items()
print(items) # Output: dict_items([('name', 'Alice'), ('age', 30), ('city', 'New York')])

for key, value in my_dict.items():
    print(f"Key: {key}, Value: {value}")
# Output:
# Key: name, Value: Alice
# Key: age, Value: 30
# Key: city, Value: New York

get(): Safe Retrieval

.get(key, default) retrieves the value for a given key. If the key doesn’t exist, it returns the default value (or None if no default is provided), avoiding errors.

1
2
3
4
5
age = my_dict.get("age")
print(age) # Output: 30

occupation = my_dict.get("occupation", "Unknown")
print(occupation) # Output: Unknown

Modifying Dictionaries

setdefault(): Adding if Absent

.setdefault(key, default) returns the value of the key, but also inserts the key with the given default value if the key is not already in the dictionary.

1
2
3
4
my_dict.setdefault("country", "USA")
print(my_dict) # Output: {'name': 'Alice', 'age': 30, 'city': 'New York', 'country': 'USA'}

#If 'country' already existed, the value would NOT be changed.

update(): Merging Dictionaries

.update(other_dict) merges another dictionary into the current one. If there are shared keys, the values from other_dict overwrite the existing ones.

1
2
3
new_data = {"age": 31, "occupation": "Engineer"}
my_dict.update(new_data)
print(my_dict) # Output: {'name': 'Alice', 'age': 31, 'city': 'New York', 'country': 'USA', 'occupation': 'Engineer'}

Resources:

Dictionary Methods Explained πŸš€

Let’s explore some handy dictionary methods in Python. Dictionaries are super useful for storing data in key-value pairs!

Removing Items πŸ—‘οΈ

pop()

  • Removes a specific key-value pair. You need to provide the key. If the key isn’t found, it raises an error (unless you provide a default value).
1
2
3
4
my_dict = {"name": "Alice", "age": 30, "city": "New York"}
popped_value = my_dict.pop("age")
print(my_dict) # {'name': 'Alice', 'city': 'New York'}
print(popped_value) # 30

popitem()

  • Removes and returns the last inserted key-value pair. Useful when you don’t care which item gets removed. Before Python 3.7, it removed an arbitrary item.
1
2
3
4
my_dict = {"name": "Alice", "age": 30, "city": "New York"}
removed_item = my_dict.popitem()
print(my_dict) # {'name': 'Alice', 'age': 30} (Order may vary before Python 3.7)
print(removed_item) # ('city', 'New York')

Clearing and Copying 🧹

clear()

  • Removes all items from the dictionary, leaving it empty.
1
2
3
my_dict = {"name": "Alice", "age": 30}
my_dict.clear()
print(my_dict) # {}

copy()

  • Creates a shallow copy of the dictionary. Changes to the copy won’t affect the original, and vice-versa (for simple data types).
1
2
3
4
5
my_dict = {"name": "Alice", "age": 30}
new_dict = my_dict.copy()
new_dict["age"] = 31
print(my_dict) # {'name': 'Alice', 'age': 30}
print(new_dict) # {'name': 'Alice', 'age': 31}

Creating from Keys πŸ”‘

fromkeys()

  • Creates a new dictionary with keys from a sequence and a common value (default is None).
1
2
3
keys = ["name", "age", "city"]
new_dict = dict.fromkeys(keys, "Unknown")
print(new_dict) # {'name': 'Unknown', 'age': 'Unknown', 'city': 'Unknown'}

Here is a resource link to get more info on Python Dictionaries: Python Dictionary Tutorial

Dictionary Comprehensions: πŸ› οΈ A Quick Guide

Tired of writing long loops to make dictionaries? Dictionary comprehensions are here to help! They offer a super concise way to create dictionaries in just one line of code. Think of it as a short and sweet shortcut.

The Basics: Unpacking the Syntax

The magic formula is: {key: value for item in iterable}. Let’s break it down:

  • key: value: This defines what each key-value pair in your dictionary will look like.
  • for item in iterable: This part is familiar! It’s just like a for loop, looping through each item in your iterable (like a list or tuple).

Examples: Putting it into Practice

Simple Transformation

Let’s say you have a list of numbers and want to create a dictionary where the number is the key and its square is the value:

1
2
3
4
numbers = [1, 2, 3, 4, 5]
squares = {num: num**2 for num in numbers}
print(squares)
# Output: {1: 1, 2: 4, 3: 9, 4: 16, 5: 25}

Adding Filters: Keeping it Selective

Want to include only even numbers? Add an if condition!

1
2
3
4
numbers = [1, 2, 3, 4, 5, 6]
even_squares = {num: num**2 for num in numbers if num % 2 == 0}
print(even_squares)
# Output: {2: 4, 4: 16, 6: 36}
  • The if num % 2 == 0 part ensures that only even numbers are processed.

Dictionary comprehensions can significantly reduce code and improve readability. They are a handy tool for any Python programmer.

Nested Dictionaries: Dictionaries within Dictionaries πŸ“š

Nested dictionaries are simply dictionaries that contain other dictionaries as values. Think of it as a dictionary where some entries point to other, smaller dictionaries. They are used to represent complex, hierarchical data.

graph LR
    ROOT["my_dict"]:::javaStyle --> PERSON["person"]:::jdbcStyle
    PERSON --> NAME["name: Alice"]:::driverStyle
    PERSON --> AGE["age: 30"]:::dbStyle
    PERSON --> ADDRESS["address"]:::useStyle
    ADDRESS --> STREET["street: 123 Main St"]:::jdbcStyle
    ADDRESS --> CITY["city: Anytown"]:::dbStyle

    classDef javaStyle fill:#ff4f81,stroke:#c43e3e,color:#fff,font-size:16px,stroke-width:3px,rx:14,shadow:6px;
    classDef jdbcStyle fill:#6b5bff,stroke:#4a3f6b,color:#fff,font-size:16px,stroke-width:3px,rx:14,shadow:6px;
    classDef driverStyle fill:#ffd700,stroke:#d99120,color:#222,font-size:16px,stroke-width:3px,rx:14,shadow:6px;
    classDef dbStyle fill:#00bfae,stroke:#005f99,color:#fff,font-size:16px,stroke-width:3px,rx:14,shadow:6px;
    classDef useStyle fill:#ff9800,stroke:#f57c00,color:#fff,font-size:16px,stroke-width:3px,rx:14,shadow:6px;

    class ROOT javaStyle;
    class PERSON jdbcStyle;
    class NAME driverStyle;
    class AGE dbStyle;
    class ADDRESS useStyle;
    class STREET jdbcStyle;
    class CITY dbStyle;

    linkStyle default stroke:#e67e22,stroke-width:3px;

Accessing Nested Values πŸ”‘

You access nested values by chaining keys, like dictionary['key1']['key2']['key3']. Each key accesses a level deeper into the structure.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
my_dict = {
    'person': {
        'name': 'Alice',
        'age': 30,
        'address': {
            'street': '123 Main St',
            'city': 'Anytown'
        }
    }
}

# Accessing Alice's age:
age = my_dict['person']['age'] # 30
# Accessing Alice's street:
street = my_dict['person']['address']['street'] # '123 Main St'

print(age)
print(street)
# 30
# 123 Main St

Practical Use Cases πŸ’Ό

  • JSON-like Data Structures: Nested dictionaries are perfect for representing data similar to JSON format. This is super useful for working with APIs and configuration files.

  • Representing Complex Objects: Like a customer object containing address and order history dictionaries.

  • Configuration Management: Storing application settings organized by category.

1
2
3
4
5
6
7
8
9
10
11
# Example of JSON-like data
data = {
    "widget": {
        "debug": "on",
        "window": {
            "name": "main_window",
            "width": 640,
            "height": 480
        }
    }
}
FeatureDictionary (dict)List (list)Tuple (tuple)
StructureKey-value pairsOrdered itemsOrdered items
MutabilityMutableMutableImmutable
AccessBy keyBy indexBy index
Syntax{}[]()
Typical UseMapping, fast lookupSequence, iterationFixed sequence, safety
Keys/IndicesKeys must be immutableIndices (0, 1, …)Indices (0, 1, …)
1
2
3
4
5
6
7
8
9
10
11
12
13
# <span style="color:#e67e22">Dictionary Fun πŸ“–: Operations and Tips</span>

Let's explore some handy dictionary tricks and how to use them wisely! Dictionaries are like real-world dictionaries: they hold _key-value_ pairs.

## <span style="color:#2980b9">Essential Dictionary Actions πŸ› οΈ</span>

- **Membership Testing ( `in` )**: Quick check to see if a key exists. Super fast! πŸ’¨

  ```python
  my_dict = {'apple': 1, 'banana': 2}
  print('apple' in my_dict)  # Output: True
  print('orange' in my_dict) # Output: False
  • Iteration: Looping through the dictionary. You can loop through keys, values, or both! πŸ”„

    1
    2
    3
    4
    5
    6
    7
    
    my_dict = {'apple': 1, 'banana': 2}
    for key in my_dict: # Loop through keys
        print(key)
    for value in my_dict.values(): # Loop through values
        print(value)
    for key, value in my_dict.items(): # Loop through keys and values
        print(f"{key}: {value}")
    
  • Merging Dictionaries ( | ): Combines two dictionaries (Python 3.9+). Think of it as a friendly handshake!🀝

    1
    2
    3
    4
    
    dict1 = {'a': 1, 'b': 2}
    dict2 = {'c': 3, 'd': 4}
    merged_dict = dict1 | dict2
    print(merged_dict) # Output: {'a': 1, 'b': 2, 'c': 3, 'd': 4}
    

Performance Notes and Best Practices πŸš€

  • Speed Matters: Dictionary lookups (using keys) are generally very fast – close to constant time! This is a big advantage.
  • Choose Keys Wisely: Use immutable (unchangeable) data types like strings, numbers, or tuples as keys. Avoid using lists!
  • Memory Management: Dictionaries can take up a fair bit of memory. Be mindful when working with very large datasets.
  • Avoid Modification during Iteration: Modifying a dictionary while looping through it can lead to unexpected behavior. Create a copy or use a list to store the elements to be deleted/modified.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#Don't do this
my_dict = {'apple': 1, 'banana': 2, 'cherry':3}
for key in my_dict:
    if my_dict[key] < 3:
        del my_dict[key]  #This is bad

#Instead you could do this:
my_dict = {'apple': 1, 'banana': 2, 'cherry':3}
keys_to_delete = []
for key in my_dict:
    if my_dict[key] < 3:
        keys_to_delete.append(key)

for key in keys_to_delete:
    del my_dict[key]

print(my_dict) #Output {'cherry': 3}

Conclusion

Hope you enjoyed the read! πŸ₯³ Now it’s your turn! What are your takeaways? Any tips you’d like to share? Drop a comment below – I’m all ears! πŸ‘‚βœοΈ

This post is licensed under CC BY 4.0 by the author.