TutorChase logo
Login
AQA A-Level Computer Science

11.7.2 Dictionary operations

Dictionaries are a powerful data structure used to store and manage data through unique keys and associated values, enabling efficient and intuitive data handling.

Inserting a key-value pair

Adding a new key-value pair to a dictionary is known as insertion. This is one of the most basic operations. A dictionary stores data in pairs, where each key is unique and associated with a specific value. When you insert a new item, you're essentially creating a new entry with a new key pointing to a value.

Python example

python

student_ages = {}  # Creates an empty dictionary
student_ages['Alice'] = 17  # Insert key 'Alice' with value 17
student_ages['Bob'] = 18
print(student_ages)

Output:

bash

{'Alice': 17, 'Bob': 18}

Pseudocode example

css

DECLARE student_ages
student_ages ← empty dictionary
student_ages['Alice'] ← 17
student_ages['Bob'] ← 18

Key points

  • Inserting a key is done by assigning a value to a key using square brackets.

  • If the key does not yet exist, the dictionary will create a new entry.

  • Keys must be immutable types such as strings, integers, or tuples. You cannot use lists or other dictionaries as keys.

Take your grades to the next level!

UPGRADING TO PREMIUM UNLOCKS
AI Tutor
AI-powered study assistant
instant feedback and guidance
Predicted Papers
Examiner-style predicted papers
based on recent exam trends
Practice Questions
All exam practice questions
by topic for each subject
Study Notes
All detailed revision notes
written by expert teachers
Cheat Sheets
Quick revision summaries
perfect for last-minute review
Past Papers
Complete collection
of practice and past exam papers
Email
Password
Confirm Password
Already have an account?

Practice Questions

FAQ

Dictionary keys must be immutable data types. This includes types like strings, integers, floats, and tuples (as long as all elements in the tuple are themselves immutable). This is because dictionary keys are hashed, and the hash value must remain constant throughout the key’s lifetime in the dictionary. Attempting to use a mutable type like a list or another dictionary as a key will raise a TypeError. For instance, d[[1, 2, 3]] = 'value' will result in an error because lists can change, and therefore cannot produce a stable hash value. This restriction ensures the integrity of the dictionary's internal structure, especially in implementations using hash tables, which rely on hash functions for fast key access. If you need to use a list-like structure as a key, consider converting it to a tuple first, e.g. d[tuple([1, 2, 3])] = 'value'. This practice guarantees key stability and consistent behaviour during dictionary operations.

On average, dictionary operations like insert, lookup, update, and delete all operate in constant time, or O(1). This efficiency comes from the use of a hash table under the hood, where the key’s hash value determines its position in memory. However, this performance is not guaranteed in all cases. Several factors can affect the speed of dictionary operations. One major factor is hash collisions, where two keys produce the same hash value and must be stored in the same slot, requiring additional handling through methods like chaining or open addressing. The dictionary's performance can also degrade if it becomes too full and needs to be resized. In such cases, all items are rehashed and moved to new locations in memory, which is temporarily more time-consuming. Additionally, using complex or expensive-to-hash keys, such as long strings or nested tuples, may slightly reduce performance. In practice, though, dictionary operations remain highly efficient for most use cases.

When you insert a key into a dictionary that already exists, the dictionary will not create a duplicate. Instead, it will automatically overwrite the existing value associated with that key. This means that the dictionary treats the operation as an update rather than a fresh insertion. For example, if student_scores = {'Liam': 80} and you then run student_scores['Liam'] = 92, the original value of 80 is replaced by 92. This behaviour is intentional and ensures that each key remains unique. Unlike lists or arrays, which allow repeated values at different indexes, dictionaries maintain key uniqueness and do not preserve older values once overwritten. This is useful in applications where the most recent information must always be stored, such as updating user preferences or tracking the latest sensor readings. If you want to retain a history of changes, you would need to store values as a list or use a nested structure.

Modifying a dictionary (e.g. adding or deleting keys) while iterating through it directly can lead to runtime errors or unexpected behaviour. This is because dictionaries are not static structures—they are dynamic and may change size during iteration, which can invalidate the iterator and result in a RuntimeError. To safely modify a dictionary during iteration, one common strategy is to create a copy of the keys or items and iterate over that instead. For example, you can use for key in list(my_dict.keys()) to loop over a stable list of keys, while still modifying the original dictionary. If you're deleting items that meet a condition, this approach prevents interference with the iteration process. Similarly, when filtering data, it’s often better to create a new dictionary using a dictionary comprehension that includes only the elements you want to keep. This ensures that the original structure remains intact and avoids unpredictable outcomes.

Using .get(key) is a safer and more flexible method of accessing values in a dictionary compared to direct access using dictionary[key]. When you use direct access and the key is not present in the dictionary, a KeyError is raised, which can interrupt your program if not handled. In contrast, .get() allows you to provide a default return value if the key doesn’t exist. For example, dictionary.get('James', 0) will return 0 instead of raising an error. This makes .get() particularly useful in cases where the dictionary is dynamically populated, where keys may or may not exist, such as in frequency counters, caches, or optional configuration settings. Direct access should be used when you are confident the key exists or when an error is the desired outcome. For example, in debugging scenarios or when catching missing keys is part of the control flow logic, direct access followed by exception handling may be more appropriate.

Hire a tutor

Please fill out the form and we'll find a tutor for you.

1/2
Your details
Alternatively contact us via
WhatsApp, Phone Call, or Email