When should I use dict.get() instead of square brackets?

Short answer

Use d[key] when a missing key means your program is broken and should stop. Use d.get(key, default) when a missing key is a normal, expected case.

python
video = {"title": "Intro to Python", "views": 197}

video["title"]          # 'Intro to Python'
video["likes"]          # KeyError — stops the program
video.get("likes")      # None
video.get("likes", 0)   # 0

#The rule of thumb

Crashing is not always bad. If a config file is missing its database_url, you want a loud KeyError at startup rather than a mysterious None failing three layers deeper.

Reach for .get() when absence is a legitimate state — an optional field, a cache lookup, a counter that has not been incremented yet.

setdefault inserts the default and returns it, which is how you group without checking first:

python
groups = {}
for video in catalogue:
    groups.setdefault(video["track"], []).append(video["title"])

collections.defaultdict does the same automatically:

python
from collections import defaultdict
groups = defaultdict(list)
for video in catalogue:
    groups[video["track"]].append(video["title"])