A hash table is a data structure that stores data as key → value pairs
and allows extremely fast lookups. In Python, the built-in dict type is implemented
as a hash table. This guide explains how hash tables work, why they are so efficient, and how to use them effectively in Python.
You will learn:
A hash table maps keys to values using a hash function. Instead of scanning through a list to find an item (O(n)), we compute an index using the key and jump directly to its position (average O(1)). This makes hash tables incredibly fast for lookups, inserts, and deletions.
Hash tables are the backbone of Python dictionaries, sets, caches, and many fast lookup systems.
A hash function converts a key into an integer called a hash code. The hash table uses this number to decide where to store the key-value pair in an internal array.
Good hash functions should be:
In Python, you can see hash values using hash():
To convert the hash into a valid index, the hash table uses the modulo operation:
index = hash(key) % table_size
Python's built-in dict type is a highly optimized hash table with:
Here are some common operations with Python dictionaries:
A collision occurs when two different keys hash to the same index. Collisions are unavoidable in finite-sized tables, so the hash table must handle them.
Two popular strategies to handle collisions are:
CPython dictionaries use a form of open addressing with probing, not simple chaining.
The load factor of a hash table is:
load_factor = number_of_elements / table_size
If the load factor becomes too high, collisions increase and performance degrades. To fix this, the hash table automatically:
Python dictionaries handle this resizing internally, so you still see average O(1) performance.
Average time complexities for hash table operations:
| Operation | Average Time | Worst Case |
|---|---|---|
| Insert | O(1) | O(n) |
| Lookup | O(1) | O(n) |
| Delete | O(1) | O(n) |
The worst case (O(n)) happens if many keys collide badly, but Python’s implementation is designed to make this extremely rare in real-world code.
Keys in a hash table must be hashable, which means:
__hash__ methodCommon hashable types:
int, float, boolstrtuple (if it contains only hashable items)Common non-hashable types:
listdictsetmy_dict = {}
# ❌ list as a key → TypeError
# my_dict[[1, 2, 3]] = "invalid"
# ✔ tuple as a key
my_dict[(1, 2, 3)] = "valid"
print(my_dict)
To understand hash tables deeply, it helps to build a simple version yourself. This example uses separate chaining (each bucket is a list of key-value pairs).
Usage example:
# Usage:
ht = HashTable()
ht.insert("name", "Alex")
ht.insert("age", 25)
ht.insert("country", "Lithuania")
print(ht.get("name")) # "Alex"
print(ht.get("age")) # 25
ht.delete("age")
print(ht.get("age")) # None
Hash tables are used in many systems for extremely fast lookup and mapping:
Hash tables use hashing for indexing and fast lookup. This is different from cryptographic hash functions, which are designed for security.
Examples of cryptographic hashes:
Cryptographic hashes are used for password storage, digital signatures, and blockchain – not for dictionary indexing.
In this guide, you learned:
Hash tables are one of the most powerful and widely used data structures. Mastering them gives you a huge advantage when designing fast and scalable applications.