Overview
An overview of how Python's dictionaries are implemented can be found in the 2017 Pycon talk, Modern Python Dictionaries A confluence of a dozen great ideas.
How to visualize reduction
I understand that a hash table will use a hashing function to reduce the universe of all possible keys down to a set m and use chaining to resolve collisions. ... I can't seem to visualize the m part of it.
The easiest visualization is with m == 2
so that hashing divides keys into two groups:
>>> from pprint import pprint
>>> def hash(n):
'Hash a number into evens or odds'
return n % 2
>>> table = [[], []]
>>> for x in [10, 15, 12, 41, 80, 13, 40, 9]:
table[hash(x)].append(x)
>>> pprint(table, width=25)
[[10, 12, 80, 40],
[15, 41, 13, 9]]
In the above example, the eight keys all get divided into two groups (the evens and the odds).
The example also works with bigger values of m such as m == 7
:
>>> table = [[], [], [], [], [], [], []]
>>> for x in [10, 15, 12, 41, 80, 13, 40, 9]:
table[x % 7].append(x)
>>> pprint(table, width=25)
[[],
[15],
[9],
[10, 80],
[],
[12, 40],
[41, 13]]
As you can see, the above example has two empty slots and slots with a collision.
Table for an empty dict
Say I create an empty dict() in python. Does python create a table with some predefined number of null entries?
Yes, Python creates eight slots for an empty table. In Python's source code, we see #define PyDict_MINSIZE 8
in cpython/Objects/dictobject.c.