Dict comprehensions
{w: len(w) for w in words}
The colon is the whole difference. Everything before it is the key, everything after is the value, and both are ordinary expressions evaluated per item.
Two patterns come up constantly. Inverting:
{v: k for k, v in prices.items()}
and building from parallel lists:
{k: v for k, v in zip(keys, values)}
though dict(zip(keys, values)) is shorter when there is no transformation to do.
Duplicate keys do not complain
{k: v for k, v in [("a", 1), ("a", 3)]}
gives {"a": 3}. The later value overwrites the earlier one, with no error and no warning. If the input might contain duplicates and you care, that is something to check for, not something Python will tell you about.
Set comprehensions
{w[0] for w in words}
Braces without a colon. It deduplicates as it builds, which is the point: "the distinct first letters" is one expression rather than a loop plus a set() call.
Remember that a set has no order, so the printed result may not match the input order and should not be relied on.
The empty-braces trap, again
{} is an empty dict — dictionaries claimed the braces long before sets existed. There is no empty-set literal at all; set() is the only way. This is worth repeating because it is the one inconsistency in an otherwise tidy family.
When to use them
Same rule as list comprehensions: when it fits on a line and reads as a sentence. A dict comprehension with a conditional key expression and a filter is a line you will re-read; a loop is fine, and often kinder.