A First Look at What's Coming in Python 3.9
Python 3.9 hit feature-complete beta in May, and the changes are small but genuinely useful for everyday code.
Python 3.9 has been in beta since May 18, which means it’s feature-complete: whatever’s in beta 1 is what’s shipping (barring bug fixes) when the final release lands in October. I’ve been poking at it over the past few weeks, and while there’s no single headline feature like the walrus operator was for 3.8, there’s a cluster of small quality-of-life changes that I think will actually get used constantly once people upgrade.
Merging dicts without the gymnastics
The one I’m most excited about is new merge operators for dictionaries: | and |=. Right now, merging two dicts means reaching for {**a, **b}, or dict(a, **b), or writing a loop, none of which read as obviously as they should. With 3.9 you’ll just write:
merged = dict_a | dict_b
And if you want to update one dict in place with another’s contents:
dict_a |= dict_b
It mirrors how set union already works with |, so it’s a consistent extension of syntax Python already had rather than something bolted on. Small thing, but it’s the kind of small thing you type often enough that it adds up.
Prefix and suffix stripping that actually does what you think
Anyone who’s been bitten by str.strip() treating its argument as a set of characters rather than a literal substring will appreciate str.removeprefix() and str.removesuffix(). Right now if you want to remove a known prefix like "https://" from a string, you either slice manually with len() math or misuse lstrip() and get subtly wrong results when the string has repeated characters. The new methods just do the obvious thing: check for an exact prefix or suffix and remove it if present, no character-set confusion. It’s a tiny API gap that’s existed for years, and I’m glad someone finally closed it.
Type hints get easier to write
The change with the biggest long-term implications is probably support for using standard collection types directly in type hints — list[int], dict[str, float], and so on — instead of needing to import List, Dict, etc. from the typing module. If you’ve written any type-annotated Python, you know the ritual of importing generic aliases just to describe a list of strings. This removes that ceremony for the common cases. It doesn’t retire typing entirely, but it should cut down a lot of import boilerplate in typical application code.
None of this is flashy, and that seems to be the theme of Python’s release cadence lately: steady ergonomic polish rather than big syntax overhauls. If you maintain libraries that need to support older Python versions, none of these are things you can rely on for a while yet, since 3.9 won’t be final until October and plenty of shops are still catching up to 3.7 or 3.8. But if you’re on the bleeding edge or just curious, the betas are up and installable now, and it’s worth kicking the tires on the dict merge operator in particular — I suspect it’ll become as automatic as list comprehensions once people get used to it.