Lesson 8 · Python data types deep dive
Python Dictionaries Explained: Keys, Methods & Nesting | Data Types #8
Video eight of the twelve-part series: dict, Python's key-value mapping type and one of the most-used data structures in the entire language. Construction,…
- CoursePython data types deep dive
- Lesson8 of 12
- Video21 min
- FormatJupyter notebook · 17 code cells
What you'll learn
Data
No separate download needed — the notebook creates or downloads everything it uses.
📓 Full notebook
Download .ipynbPython Data Types Deep-Dive, Video 8: Dictionaries (dict)#
- Video eight of the twelve-part series: dict, Python's key-value mapping type and one of the most-used data structures in the entire language.
- Construction, access, all eleven public dict methods, views, comprehensions, and merging.
- Let's get into it.
Part 1: What Makes dict Different#
person = {'name': 'Ana', 'age': 29, 'city': 'Lima'}
print(type(person))
print(len(person))
print(person['name'])
person['age'] = 30
print(person)
Part 2: Dict Literals and Construction#
empty = {}
also_empty = dict()
from_kwargs = dict(name='Sam', age=25)
from_pairs = dict([('a', 1), ('b', 2)])
keys = ['x', 'y', 'z']
values = [10, 20, 30]
from_zip = dict(zip(keys, values))
print(empty, also_empty, from_kwargs, from_pairs, from_zip)
defaults = dict.fromkeys(['a', 'b', 'c'], 0)
print(defaults)
no_default = dict.fromkeys(['x', 'y', 'z'])
print(no_default)
Part 3: Accessing Values: indexing and get()#
person = {'name': 'Ana', 'age': 29}
print(person['name'])
try:
print(person['email'])
except KeyError as e:
print(f'Caught: {e}')
print(person.get('email'))
print(person.get('email', 'not provided'))
print(person.get('name', 'not provided'))
Part 4: Adding and Updating: assignment, update(), setdefault()#
person = {'name': 'Ana'}
person['age'] = 29
print(person)
person.update({'age': 30, 'city': 'Lima'})
print(person)
person.update(country='Peru', age=31)
print(person)
counts = {'apple': 3}
result = counts.setdefault('apple', 0)
print(result, counts)
result = counts.setdefault('banana', 0)
print(result, counts)
counts.setdefault('banana', 0)
counts['banana'] += 1
print(counts)
Part 5: Removing: pop(), popitem(), clear()#
person = {'name': 'Ana', 'age': 29, 'city': 'Lima'}
age = person.pop('age')
print(age, person)
missing = person.pop('email', 'no email on file')
print(missing)
try:
person.pop('email')
except KeyError as e:
print(f'Caught: {e}')
stack_dict = {'a': 1, 'b': 2, 'c': 3}
last_pair = stack_dict.popitem()
print(last_pair, stack_dict)
stack_dict.clear()
print(stack_dict)
Part 6: Views: keys(), values(), items()#
scores = {'Ana': 85, 'Sam': 92, 'Lee': 78}
print(scores.keys())
print(scores.values())
print(scores.items())
for key in scores.keys():
print(key)
for key in scores:
print(key)
scores = {'Ana': 85, 'Sam': 92, 'Lee': 78}
for name, score in scores.items():
print(f'{name}: {score}')
view = scores.keys()
scores['Lee'] = 100
print(view)
Part 7: copy() and Copy Semantics#
original = {'a': 1, 'b': 2}
alias = original
alias['c'] = 3
print(original)
print(original is alias)
real_copy = original.copy()
real_copy['d'] = 4
print(original)
print(real_copy)
nested = {'user': {'name': 'Ana', 'tags': ['admin']}}
shallow = nested.copy()
shallow['user']['tags'].append('verified')
print(nested)
import copy as copy_module
deep = copy_module.deepcopy(nested)
deep['user']['tags'].append('new')
print(nested)
print(deep)
Part 8: Dict Comprehensions#
squares = {n: n ** 2 for n in range(6)}
print(squares)
words = ['apple', 'kiwi', 'banana']
lengths = {w: len(w) for w in words}
print(lengths)
scores = {'Ana': 85, 'Sam': 45, 'Lee': 92}
passing = {name: score for name, score in scores.items() if score >= 60}
print(passing)
swapped = {value: key for key, value in scores.items()}
print(swapped)
Part 9: Merging Dictionaries#
defaults = {'theme': 'light', 'font_size': 12}
overrides = {'font_size': 16, 'language': 'en'}
merged = defaults | overrides
print(merged)
print(defaults)
defaults |= overrides
print(defaults)
Part 10: Nested Dictionaries#
company = {
'name': 'Acme',
'employees': {
'Ana': {'role': 'engineer', 'salary': 95000},
'Sam': {'role': 'designer', 'salary': 85000}
}
}
print(company['employees']['Ana']['role'])
for emp_name, details in company['employees'].items():
print(f"{emp_name}: {details['role']}")
Part 11: Common Patterns and Pitfalls#
valid = {(1, 2): 'point', 'name': 'value', 42: 'answer'}
print(valid)
try:
invalid = {['a', 'b']: 'value'}
except TypeError as e:
print(f'Caught: {e}')
def broken_tally(item, counts={}):
counts[item] = counts.get(item, 0) + 1
return counts
print(broken_tally('a'))
print(broken_tally('a'))
print(broken_tally('b'))
def fixed_tally(item, counts=None):
if counts is None:
counts = {}
counts[item] = counts.get(item, 0) + 1
return counts
print(fixed_tally('a'))
print(fixed_tally('a'))
Wrap-Up: What You Learned#
- dict maps keys to values, is mutable, and preserves insertion order.
- Construction: literals, dict(), fromkeys, from pairs, and from zipped sequences.
- Access: square brackets versus the safer get().
- Adding and updating: assignment, update(), setdefault().
- Removing: pop(), popitem(), clear().
- Views: keys(), values(), items(), and their live, auto-syncing behavior.
- Copy semantics, dict comprehensions, merging with the pipe operator, and nested dictionaries.
- Hashable-key requirements and the mutable-default-argument pitfall.
- That's all eleven public dict methods covered. Next up: set, for unique, unordered collections.
Found this useful?
All lessons, notebooks and datasets here are free. If they helped you, a coffee keeps new lessons coming.



