Contents

Python Quick Guide - Step 1 Basic Syntax and Data Types (9) - Dictionaries

Info
  • This course is designed to help you learn the basics of Python programming as quickly as possible through hands-on practice.
  • The “Style Guide” sections primarily cover guidelines from PEP8 for writing clean Python code.
  • You can run and see the results of each code example.
    Feel free to experiment with the code - reloading the page will reset the content.

This is a continuation of “Step 1: Basic Syntax and Data Types”.

As a data type for grouping elements, Python offers dictionaries (dict), which take a different approach from lists and tuples.
Dictionaries store “key” and “value” pairs, similar to how a real dictionary relates “headwords” to their “definitions”.

  • Dictionaries are created by placing key: value pairs separated by commas (,) inside curly braces ({, }).
  • An empty dictionary can be created with {}.
  • You can also create dictionaries using the dict function.
Style Guide
  • Always add one space after a colon (:).
  • Always add one space after a comma (,).
  • For longer dictionaries, breaking them into multiple lines improves readability.
    • Each element should be indented with 4 spaces at the beginning of the line.
    • Add a trailing comma after the last element.
📚Exercise

Create a dictionary with the following product information:

  • Product name (product): Bread
  • Price (price): 250
  • Expiration date (expiration_date): “2025-06-08” (enter as a string)
  • Stock (stock): 15
  • New product (is_new): False

Once you’ve successfully created it, try creating the same dictionary using the dict function.

Dictionary keys must be immutable (unchangeable) objects.

  • Numbers, strings, (tuples without mutable elements), and boolean values are immutable, so they can be used as keys.
  • Lists and dictionaries cannot be used as keys.
    • Mutable (changeable) objects cannot be used as keys because if their values change, they would no longer function properly as keys. (See the column for details)
Column: Dictionary Keys and Hashability

Python dictionaries use a technique called “hashing” to quickly look up values using their keys.
This involves calculating a special “hash value” for each key, which is then used for lookups.

An object that can have a hash value calculated is called “hashable”.
Whether an object is hashable determines whether it can be used as a dictionary key.

Basic characteristics include:

  1. Immutable objects are typically hashable
  2. Mutable objects are typically not hashable

The reason mutable objects aren’t hashable is that if their content changes, their hash value would also change, causing the dictionary’s lookup system to malfunction.

To summarize:

  • Hashable (can be used as dictionary keys): strings, numbers, tuples (if all contents are immutable), None, boolean values
  • Not hashable (cannot be used as dictionary keys): lists, dictionaries, etc.

Technically, it’s possible to define proper hash values for mutable objects so they can be used as keys, but this practice is uncommon and makes maintaining data integrity difficult.
This is an advanced topic - for now, just remember that “immutable objects can be used as keys”.

You’ll understand this better when you learn about object-oriented programming later.

  • Dictionary elements are retrieved by specifying their keys.
  • Attempting to access a non-existent key results in a KeyError.
  • To add a new key-value pair, simply assign a value to a new key.
  • To update an existing key, assign a new value to that key.
  • You can check if a key exists in a dictionary using the in operator.
  • The get method allows you to retrieve a value with a default return value if the key doesn’t exist.
    • If no default is specified, None is returned when the key doesn’t exist.
  • The keys method returns a list-like view of all keys in the dictionary.
    • The return value is a dict_keys type, which is different from a list but supports operations like checking for existence with in.
  • The values method returns a list-like view of all values in the dictionary.
    • The return value is a dict_values type, which is different from a list but supports operations like checking for existence with in.
  • The items method returns a list-like view of all key-value pairs (as tuples) in the dictionary.
    • The return value is a dict_items type, which is different from a list but supports operations like checking for existence with in.
  • The returned dict_keys, dict_values, and dict_items types have list-like properties, but they don’t support all list operations like index-based element retrieval.
View Objects

The .keys(), .values(), and .items() methods return view objects (dict_keys, dict_values, dict_items) with these characteristics:

  • Dynamic References - They are dynamic references to the dictionary’s data and automatically update when the dictionary changes.
  • Memory Efficiency - They don’t copy the dictionary’s data, making them memory-efficient.
  • Iterable - You can iterate over them in loops (you’ll learn about loops later).
  • Immutable Views - You can’t directly modify the views (they change only when the underlying dictionary changes).
  • If you want to use them as lists, convert them using the list function. Converting to a list breaks the dynamic connection with the original dictionary and creates a snapshot.
  • The update method lets you update the current dictionary with the contents of another dictionary.
  • If keys overlap, values are overwritten, and new keys are added.
  • The pop method removes an element with the specified key and returns its value.
    • The return value is the value (not the key) corresponding to the specified key.
    • You can specify a default value as the second argument to return if the key doesn’t exist.
    • If no default value is specified and the key doesn’t exist, a KeyError is raised.

Like lists, dictionaries have a copy method for creating shallow copies.

Be aware that this is a shallow copy, so nested elements are not copied, just like with lists.

  • For a deep copy, use the deepcopy function from the copy module, just like with lists.
  • Applying the bool function to a dictionary returns False for an empty dictionary ({}) and True otherwise.
When to Use Dictionaries, Tuples, and Lists

Each data type we’ve learned has different characteristics and appropriate uses:

  • Dictionaries (dict) are appropriate when:

    • You need to associate data using key-value pairs
    • You want to quickly look up data by names or IDs
    • You want to add meaningful labels to data
  • Tuples (tuple) are appropriate when:

    • You’re dealing with a fixed collection of data that won’t change
    • You want to group multiple values but don’t need to modify them later
    • You need an immutable sequence to use as a dictionary key
  • Lists (list) are appropriate when:

    • The order of elements matters
    • You need to add, remove, or modify elements
    • You want to collect multiple elements of the same type

Understanding each type’s characteristics helps you choose the most appropriate one for your situation.

Let’s solve some practice problems to review dictionary operations.

📚Exercise 1: Basic Dictionary Operations

Perform the following operations on a dictionary that manages products and prices:

  1. Create a dictionary named menu with the following products and prices:
    • “Coffee”: 300
    • “Tea”: 280
    • “Sandwich”: 350
    • “Pasta”: 600
  2. Add “Salad” (500) to the menu
  3. Update the price of “Coffee” to 320
  4. Check if “Cake” is in the menu and display the result
  5. Display the price of “Omelet”. If it’s not on the menu, display “Not available” (use the get method)
  6. Remove “Pasta” from the menu and display its price
  7. Display the list of all product-price pairs
Sample Solution
📚Exercise 2: Contact Management

Implement a contact directory using dictionaries.

  1. Create an empty dictionary called contacts
  2. Add the following contact information:
    • "John Smith": {"email": "[email protected]", "phone": "555-1234", "city": "New York"}
    • "Mary Johnson": {"email": "[email protected]", "phone": "555-5678", "city": "Los Angeles"}
  3. Add "Robert Brown" with email "[email protected]", phone "555-3333", and city "Chicago"
  4. Update "John Smith"’s phone number to "555-9876"
  5. Display all of "Mary Johnson"’s contact information
  6. Display all contact names (use the keys method)
  7. You found an old address book with these contacts - add them all at once:
    • "William Davis": {"email": "[email protected]", "phone": "555-2222", "city": "Miami"}
    • "John Smith": {"email": "[email protected]", "phone": "555-7777", "city": "Boston"}
      (Note that "John Smith" already exists and will be updated)
  8. Display all contact information after the update
Sample Solution
📚Exercise 3: Inventory Management System

Create a system to manage product inventory. Use dictionaries to store product information (name, price, stock).

  1. Create an inventory dictionary with these initial products:

    • “A001”: {“name”: “Laptop”, “price”: 85000, “stock”: 10}
    • “A002”: {“name”: “Smartphone”, “price”: 60000, “stock”: 15}
    • “A003”: {“name”: “Tablet”, “price”: 45000, “stock”: 8}
  2. Add a new product “A004” (name: “Wireless Earbuds”, price: 15000, stock: 20)

  3. Update product “A002” to have price 55000 and stock 20

  4. Check if product “A005” exists in inventory and display the result

  5. Remove product “A003”, retrieve its information, and display it

Sample Solution
Dictionary Order Preservation

In Python 3.7 and later, dictionaries maintain the insertion order of keys.
In earlier versions, the order of dictionary elements was not guaranteed.

Dictionaries and JSON Format

Python dictionaries are very similar to the JSON (JavaScript Object Notation) format. JSON is widely used as a data exchange format, and in Python, the standard library’s json module makes it easy to convert between JSON and dictionaries (you’ll learn more about this later).

This is why it’s common to work with JSON data from APIs or files as Python dictionaries.

Column: Time Complexity of Dictionary Operations

Like with lists, let’s examine the time complexity of dictionary operations.

Python dictionaries use a mechanism called hash tables, which makes most operations very fast.
Notably, accessing elements by key is as fast as accessing list elements by index,
and it remains efficient regardless of how much data the dictionary contains.

Note on time complexity notation:

  • O(1): Processed in constant time regardless of input size
  • O(n): In the worst case, processing time is proportional to the number of elements n in the dictionary
  • O(k): In the worst case, processing time is proportional to the number of elements k in the second input dictionary
Operation Time Complexity Description
dict[key] (element retrieval) O(1) (average) Usually constant time, but could be O(n) in case of numerous hash collisions
dict[key] = x (adding/updating) O(1) (average) Usually constant time, but could be O(n) when resizing and rehashing is needed
key in dict (key existence check) O(1) (average) Usually constant time, but could be O(n) in case of numerous hash collisions
len(dict) O(1) Always constant time as the dictionary size is tracked by an internal counter
.get(key, default) O(1) (average) Like dict[key], usually constant time but could be O(n) in worst case
.pop(key, default) O(1) (average) Key lookup and deletion usually constant time, but could be O(n) with hash collisions
.update(dict2) O(k) (average) Usually proportional to the number of elements k in the second dictionary, but could be O(n+k) if rehashing is needed
.keys(), .values(), .items() O(1) Only creates view objects without copying the internal data structure
list(dict.keys()) etc. O(n) Converting views to lists copies all elements, so proportional to the number of elements
.copy() O(n) Creates a shallow copy of all elements, so proportional to the number of elements

Related Content