You are currently viewing Python Dictionaries

Python Dictionaries

Python, a versatile and powerful programming language, is renowned for its simplicity and readability. It offers a wide range of data structures to handle information effectively, and one of the most fundamental and frequently used ones is the dictionary. Python dictionaries provide a flexible way to store and manipulate data, and they are an essential tool for any Python programmer. In this article, we will explore Python dictionaries, their features, use cases, and how they can enhance your programming skills.

What is a Dictionary?

A dictionary is an unordered collection of key-value pairs. It’s a versatile data structure that allows you to store and retrieve data using a unique key for each value. Dictionaries are defined using curly braces {} and follow a key: value pattern. Keys must be unique and immutable, while values can be of any data type, including numbers, strings, lists, or even other dictionaries.

if __name__ == "__main__":
    # Check if the script is the main program.

    person = {
        "name": "Edward",
        "age": 28,
        "city": "Lusaka"
    }
    
    print(person)  # Output: {'name': 'Edward', 'age': 28, 'city': 'Lusaka'}

The person dictionary defined in this example, “name”, “age”, and “city” are the keys, while “Edward”, 28, and “Lusaka” are the corresponding values.

Creating Dictionaries

Creating dictionaries in Python is straightforward. You can initialize an empty dictionary or create one with initial key-value pairs using curly braces {}.

if __name__ == "__main__":
    # Check if the script is the main program.

    # Creating an empty dictionary
    empty_dict = {}

    print(empty_dict)  # Output: {}

    # Creating a dictionary with key-value pairs
    person = {
        "name": "Edward",
        "age": 28,
        "city": "Lusaka"
    }

    print(person)  # Output: {'name': 'Edward', 'age': 28, 'city': 'Lusaka'}

Dictionaries can also be created using the dict() constructor:

if __name__ == "__main__":
    # Check if the script is the main program.

    person = dict(name="Edward", age=28, city="Lusaka")
    
    print(person)  # Output: {'name': 'Edward', 'age': 28, 'city': 'Lusaka'}

Dictionary Comprehensions

Similar to list comprehensions, Python allows you to create dictionaries in a concise and readable way using dictionary comprehensions. They provide an elegant means of creating dictionaries based on existing iterables or specific conditions. Here’s an example that creates a dictionary of squares for numbers 1 to 5:

if __name__ == "__main__":
    # Check if the script is the main program.

    squares = {x: x**2 for x in range(1, 6)}

    print(squares)  # Output: {1: 1, 2: 4, 3: 9, 4: 16, 5: 25}

Dictionary Operations

Accessing Values

One of the primary reasons for using dictionaries is efficient value retrieval. To access a value in a dictionary, you simply provide the key within square brackets, like this:

if __name__ == "__main__":
    # Check if the script is the main program.

    person = {
        "name": "Edward",
        "age": 28,
        "city": "Lusaka"
    }

    name = person['name']

    print(name)  # Output: Edward

This code retrieves the value associated with the ‘name’ key, which is ‘Edward’ in this case. If you try to access a key that doesn’t exist, you’ll encounter a KeyError. To avoid this, you can use the get() method, which allows you to provide a default value. If you don’t, None is assumed.

if __name__ == "__main__":
    # Check if the script is the main program.

    person = {
        "name": "Edward",
        "age": 28,
        "city": "Lusaka"
    }

    language = person.get('language', 'JavaScript')

    print(language)  # Output: JavaScript

Modifying Values

Dictionaries are mutable, meaning you can change their values. To modify a value in a dictionary, access it using its key and assign a new value, as shown here:

if __name__ == "__main__":
    # Check if the script is the main program.

    person = {
        "name": "Edward",
        "age": 28,
        "city": "Lusaka"
    }

    print(person)  # Output: {'name': 'Edward', 'age': 28, 'city': 'Lusaka'}

    # Modify age to 31
    person['age'] = 31

    print(person)  # Output: {'name': 'Edward', 'age': 31, 'city': 'Lusaka'}

Adding New Key-Value Pairs

To add a new key-value pair to a dictionary, simply use the same square bracket notation and assign a value to a key that doesn’t exist in the dictionary:

if __name__ == "__main__":
    # Check if the script is the main program.

    person = {
        "name": "Edward",
        "age": 28,
        "city": "Lusaka"
    }

    person['occupation'] = 'Software Developer'

    print(person)  # Output: {'name': 'Edward', 'age': 28, 'city': 'Lusaka', 'occupation': 'Software Developer'}

Removing a Key-Value Pair

In Python dictionaries, removing a key-value pair is a straightforward operation. You can use the del statement or the pop() method to delete a specific item from the dictionary.

Using del Statement

The del statement allows you to remove a key-value pair by specifying the key you want to delete. Here’s how you can do it:

if __name__ == "__main__":
    # Check if the script is the main program.

    person = {
        "name": "Edward",
        "age": 28,
        "city": "Lusaka"
    }

    # Removing a key-value pair using del
    del person['city']

    print(person)  # Output: {'name': 'Edward', 'age': 28}

In this example, the key ‘city’ and its associated value will be removed from the person dictionary. If the key is not found, it raises a KeyError.

Using pop() Method

The pop() method is an alternative way to remove a key-value pair while also allowing you to retrieve the value associated with the key. If the key is not found, it raises a KeyError unless a default value is provided.

if __name__ == "__main__":
    # Check if the script is the main program.

    person = {
        "name": "Edward",
        "age": 28,
        "city": "Lusaka"
    }

    # Removing a key-value pair using pop()
    removed_value = person.pop('city')

    print(removed_value)  # Output: Lusaka

    print(person)  # Output: {'name': 'Edward', 'age': 28}

In this code, the key ‘city’ is removed from person, and the value ‘Lusaka’ is stored in the removed_value variable. If the key doesn’t exist in the dictionary, it would raise a KeyError.

Using pop() with a Default Value

You can also use the pop() method with a default value, which prevents a KeyError if the key is not found in the dictionary:

if __name__ == "__main__":
    # Check if the script is the main program.

    person = {
        "name": "Edward",
        "age": 28,
        "city": "Lusaka"
    }

    # Removing a key-value pair using pop() with a default value
    removed_value = person.pop('country', 'Not found')

    print(removed_value)  # Output: Not Found
    
    print(person)  # Output: {'name': 'Edward', 'age': 28, 'city': 'Lusaka'}

In this case, if the key ‘country’ is not in the dictionary, removed_value will be set to ‘Not found’ instead of raising an error.

Clearing the Entire Dictionary

If you need to remove all key-value pairs from a dictionary, you can use the clear() method:

if __name__ == "__main__":
    # Check if the script is the main program.

    person = {
        "name": "Edward",
        "age": 28,
        "city": "Lusaka"
    }

    # Clearing the entire dictionary
    person.clear()

    print(person)  # Output: {}

This will leave you with an empty dictionary, effectively removing all key-value pairs.

Nested Dictionaries

Python dictionaries can also be nested, meaning a dictionary can contain other dictionaries. This feature is useful for organizing data hierarchically. Consider a nested dictionary representing a person’s contact information:

if __name__ == "__main__":
    # Check if the script is the main program.

    person = {
        'name': 'Edward',
        'address': {
            'street': '123 Main St',
            'city': 'Lusaka',
            'zip': '00000'
        },
        'phone_numbers': {
            'home': '+260960726800',
            'work': '+260973683600'
        }
    }

    street = person['address']['street']
    print(street)  # Output: 123 Main St

    city = person['address']['city']
    print(city)  # Output: Lusaka

    zip_code = person['address']['zip']
    print(zip_code)  # Output: 00000

With nested dictionaries, you can access specific pieces of information by chaining keys, like person[‘address’][‘street’] to get the street, person[‘address’][‘city’] to get the city, and person[‘address’][‘zip’] to get the zip code.

Iterating Through a Dictionary

Dictionaries can be iterated in various ways. Here, we explore some common techniques:

Iterating Through Keys

You can loop through the keys using a for loop:

if __name__ == "__main__":
    # Check if the script is the main program.

    person = {
        'name': 'Edward',
        'age': 28,
        'city': 'Lusaka'
    }

    # Iterating through keys
    for key in person:
        print(key)

Iterating Through Values

If you’re interested in the values, you can iterate through them:

if __name__ == "__main__":
    # Check if the script is the main program.

    person = {
        'name': 'Edward',
        'age': 28,
        'city': 'Lusaka'
    }

    # Iterating through values
    for value in person.values():
        print(value)

Iterating Through Key-Value Pairs

To loop through both keys and values simultaneously, you can use items():

if __name__ == "__main__":
    # Check if the script is the main program.

    person = {
        'name': 'Edward',
        'age': 28,
        'city': 'Lusaka'
    }

    # Iterating through key-value pairs
    for key, value in person.items():
        print(f"{key}: {value}")

Dictionary Methods

Python provides a wide range of methods for working with dictionaries. Here are some of the most commonly used ones:

keys()

This method returns a list of all the keys in the dictionary:

if __name__ == "__main__":
    # Check if the script is the main program.

    person = {
        'name': 'Edward',
        'age': 28,
        'city': 'Lusaka'
    }

    # Getting all keys
    keys = person.keys()

    print(list(keys))  # Output: ['name', 'age', 'city']

values()

The values() method returns a list of all the values:

if __name__ == "__main__":
    # Check if the script is the main program.

    person = {
        'name': 'Edward',
        'age': 28,
        'city': 'Lusaka'
    }

    # Getting all values
    values = person.values()

    print(list(values))  # Output: ['Edward', 28, 'Lusaka']

items()

items() returns a list of key-value pairs as tuples:

if __name__ == "__main__":
    # Check if the script is the main program.

    person = {
        'name': 'Edward',
        'age': 28,
        'city': 'Lusaka'
    }

    # Getting key-value pairs
    items = person.items()

    print(list(items))  # Output: [('name', 'Edward'), ('age', 28), ('city', 'Lusaka')]

copy()

copy() creates a shallow copy of the dictionary:

if __name__ == "__main__":
    # Check if the script is the main program.

    person = {
        'name': 'Edward',
        'age': 28,
        'city': 'Lusaka'
    }

    # Creating a copy of the dictionary
    person_copy = person.copy()

    print(person_copy)  # Output: {'name': 'Edward', 'age': 28, 'city': 'Lusaka'}

update()

update() merges two dictionaries. If there are overlapping keys, the values from the second dictionary overwrite the values in the first dictionary:

if __name__ == "__main__":
    # Check if the script is the main program.

    person = {
        'name': 'Edward',
        'age': 28,
        'city': 'Lusaka'
    }

    # Updating a dictionary
    person.update({"language": "English", "major": "Computer Programming"})
    
    print(person)
    # Output: {'name': 'Edward', 'age': 28, 'city': 'Lusaka', 'language': 'English', 'major': 'Computer Programming'}

defaultdict

Python’s collections module brings us a powerful tool known as defaultdict. This dictionary variation serves as a solution to a common issue when working with dictionaries: handling missing keys. It automatically provides default values for keys that have not been defined. This can greatly simplify your code, reduce the need for manual error-checking, and streamline various data processing tasks.

Creating a defaultdict

With defaultdict, you can specify a default factory function for your dictionary. This function will be invoked whenever a new key is accessed for the first time. Common choices for the factory function are int, list, set, or any other callable. The factory function sets the default value for the missing key based on its return type.

Here’s an example using defaultdict with the factory function int:

from collections import defaultdict

if __name__ == "__main__":
    # Check if the script is the main program.

    # Creating a defaultdict
    student_scores = defaultdict(int)

    student_scores["math"] = 95

    print(student_scores["english"])  # Output: 0

In this code example, if you access a key that doesn’t exist, defaultdict will return 0 as the default value because int() returns 0.

Simplifying Code with defaultdict

One of the primary benefits of defaultdict is that it simplifies code when dealing with missing keys. Consider a scenario where you want to count the frequency of letters in a string. Using a regular dictionary, the code can become cumbersome:

if __name__ == "__main__":
    # Check if the script is the main program.

    # Counting letter frequency using a regular dictionary
    text = "apple"
    letter_count = {}

    for letter in text:
        if letter in letter_count:
            letter_count[letter] += 1
        else:
            letter_count[letter] = 1

    print(letter_count)  # Output: {'a': 1, 'p': 2, 'l': 1, 'e': 1}

The above code requires explicit checks for missing keys and initializing them to one. In contrast, using defaultdict with int as the factory function makes this task more concise:

from collections import defaultdict

if __name__ == "__main__":
    # Check if the script is the main program.

    # Counting letter frequency using a defaultdict
    text = "apple"
    letter_count = defaultdict(int)

    for letter in text:
        letter_count[letter] += 1

    print(dict(letter_count))  # Output: {'a': 1, 'p': 2, 'l': 1, 'e': 1}

With defaultdict, you can directly increment the count for each letter without explicitly handling missing keys.

Custom Default Values

While int is a commonly used factory function for defaultdict, you can also create custom default values by providing a different callable. For instance, if you want to set a default value of “Not Found” for missing keys, you can use a custom factory function:

from collections import defaultdict

def not_found():
    return "Not Found"

if __name__ == "__main__":
    # Check if the script is the main program.

    # Creating a defaultdict with a custom default value
    student_scores = defaultdict(not_found)

    student_scores["math"] = 95

    print(student_scores["english"])  # Output: "Not Found"

In this example, when you access the “english” key, which does not exist, the factory function not_found returns “Not Found” as the default value.

Counter

Python’s collections module offers another handy tool called Counter. It’s not just any dictionary; it’s a specialized dictionary subclass designed for one specific task—counting hashable objects. Counter excels in efficiently tallying the frequency of elements in a sequence, making it a valuable tool for various data analysis and manipulation tasks.

Counting Elements in a Sequence

The primary purpose of Counter is to count the occurrences of elements in a sequence. This can be particularly useful when working with lists, strings, or any iterable data. Consider a scenario where you have a list of fruits and want to find out how many times each fruit appears:

from collections import Counter

if __name__ == "__main__":
    # Check if the script is the main program.

    fruits = ['apple', 'banana', 'apple', 'cherry', 'banana', 'cherry']

    # Create a Counter object
    fruit_counter = Counter(fruits)
    
    print(fruit_counter)  # Output: Counter({'apple': 2, 'banana': 2, 'cherry': 2})

Accessing Counts

To access the count of a specific element, you can simply use the element as the key in the Counter object:

from collections import Counter

if __name__ == "__main__":
    # Check if the script is the main program.

    fruits = ['apple', 'banana', 'apple', 'cherry', 'banana', 'cherry']

    # Create a Counter object
    fruit_counter = Counter(fruits)

    # Accessing the count of a specific element
    print(fruit_counter['apple'])  # Output: 2

In this example, fruit_counter[‘apple’] returns 2 because “apple” appears twice in the list.

Counting Letters in a String

You’re not limited to counting elements in lists; Counter can also be applied to strings. Let’s say you have a string and want to know how many times each letter appears:

from collections import Counter

if __name__ == "__main__":
    # Check if the script is the main program.

    # Counting letters in a string using Counter
    text = "apple"
    letter_counter = Counter(text)

    print(letter_counter)  # Output: Counter({'p': 2, 'a': 1, 'l': 1, 'e': 1})

Working with Other Iterables

Counter is not limited to lists and strings; it can be used with any iterable. This flexibility makes it an excellent choice for a wide range of tasks, from analyzing text data to processing data from databases.

The most_common() Method

In many scenarios, you might be interested in finding the most common elements. Counter simplifies this task with the most_common() method. This method returns a list of the n most common elements and their counts, sorted from most common to least common.

from collections import Counter

if __name__ == "__main__":
    # Check if the script is the main program.

    fruits = ['apple', 'banana', 'apple', 'cherry', 'banana', 'cherry']

    # Create a Counter object
    fruit_counter = Counter(fruits)

    # Finding the most common element with most_common()
    common_fruits = fruit_counter.most_common(1)

    print(common_fruits)  # Output: [('apple', 2)]

Conclusion

Python dictionaries are a powerful tool for managing and manipulating data in a structured and efficient manner. With their ability to store, retrieve, and modify data using keys, dictionaries offer a versatile solution for a wide range of programming tasks. Understanding the fundamentals and best practices for using dictionaries will enable you to write more efficient and readable Python code.

As you continue your journey with Python, remember to leverage dictionaries whenever you need a data structure that pairs keys with values. Whether it’s for configuration management, data aggregation, or any other application, Python dictionaries are a valuable resource in your programming toolkit.

I hope you found this article informative and useful. If you would like to receive more content, please consider subscribing to our newsletter.

Leave a Reply